diff --git a/pkg/feeds/feed_types.go b/pkg/feeds/feed_types.go index 6dc61ffd..dcba8162 100644 --- a/pkg/feeds/feed_types.go +++ b/pkg/feeds/feed_types.go @@ -18,4 +18,5 @@ const ( FeedTypeS3 = FeedType("S3") FeedTypeOCIRegistry = FeedType("OciRegistry") FeedTypeGcsStorage = FeedType("GcsStorage") + FeedTypePyPI = FeedType("PyPi") ) diff --git a/pkg/feeds/feed_utilities.go b/pkg/feeds/feed_utilities.go index 412836ab..3eb2a0e9 100644 --- a/pkg/feeds/feed_utilities.go +++ b/pkg/feeds/feed_utilities.go @@ -174,6 +174,15 @@ func ToFeed(feedResource *FeedResource) (IFeed, error) { } ociFeed.FeedURI = feedResource.FeedURI feed = ociFeed + case FeedTypePyPI: + pyPiFeed, err := NewPyPiFeed(feedResource.GetName(), feedResource.FeedURI) + if err != nil { + return nil, err + } + pyPiFeed.DownloadAttempts = feedResource.DownloadAttempts + pyPiFeed.DownloadRetryBackoffSeconds = feedResource.DownloadRetryBackoffSeconds + pyPiFeed.FeedURI = feedResource.FeedURI + feed = pyPiFeed default: return nil, errors.New("unknown feed type: " + fmt.Sprint(feedResource.GetFeedType())) } @@ -315,6 +324,11 @@ func ToFeedResource(feed IFeed) (*FeedResource, error) { case FeedTypeOCIRegistry: ociFeed := feed.(*OCIRegistryFeed) feedResource.FeedURI = ociFeed.FeedURI + case FeedTypePyPI: + pyPiFeed := feed.(*PyPiFeed) + feedResource.DownloadAttempts = pyPiFeed.DownloadAttempts + feedResource.DownloadRetryBackoffSeconds = pyPiFeed.DownloadRetryBackoffSeconds + feedResource.FeedURI = pyPiFeed.FeedURI case FeedTypeOctopusProject: // nothing to copy } diff --git a/pkg/feeds/is_nil.go b/pkg/feeds/is_nil.go index fedff912..ae682862 100644 --- a/pkg/feeds/is_nil.go +++ b/pkg/feeds/is_nil.go @@ -22,6 +22,8 @@ func IsNil(i interface{}) bool { return v == nil case *OctopusProjectFeed: return v == nil + case *PyPiFeed: + return v == nil default: return v == nil } diff --git a/pkg/feeds/pypi_feed.go b/pkg/feeds/pypi_feed.go new file mode 100644 index 00000000..d8f579d9 --- /dev/null +++ b/pkg/feeds/pypi_feed.go @@ -0,0 +1,49 @@ +package feeds + +import ( + "github.com/OctopusDeploy/go-octopusdeploy/v2/internal" + "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/core" + "github.com/go-playground/validator/v10" + "github.com/go-playground/validator/v10/non-standard/validators" +) + +// PyPiFeed represents a PyPI feed. +type PyPiFeed struct { + DownloadAttempts int `json:"DownloadAttempts"` + DownloadRetryBackoffSeconds int `json:"DownloadRetryBackoffSeconds"` + FeedURI string `json:"FeedUri,omitempty"` + Username string `json:"Username,omitempty"` + Password *core.SensitiveValue `json:"Password,omitempty"` + + feed +} + +// NewPyPiFeed creates and initializes a PyPI feed. +func NewPyPiFeed(name string, feedURI string) (*PyPiFeed, error) { + if internal.IsEmpty(name) { + return nil, internal.CreateRequiredParameterIsEmptyOrNilError("name") + } + + feed := PyPiFeed{ + DownloadAttempts: 5, + DownloadRetryBackoffSeconds: 10, + FeedURI: feedURI, + feed: *newFeed(name, FeedTypePyPI), + } + + if err := feed.Validate(); err != nil { + return nil, err + } + + return &feed, nil +} + +// Validate checks the state of this PyPI feed and returns an error if invalid. +func (p *PyPiFeed) Validate() error { + v := validator.New() + err := v.RegisterValidation("notblank", validators.NotBlank) + if err != nil { + return err + } + return v.Struct(p) +}