diff --git a/go.mod b/go.mod index 9ec1167fa4..0af28dfaf4 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/hashicorp/terraform-plugin-sdk v1.0.0 github.com/mitchellh/go-homedir v1.1.0 github.com/nicolai86/scaleway-sdk v0.0.0-20181024210327-b20018e944c4 - github.com/scaleway/scaleway-sdk-go v1.0.0-beta.5.0.20200114152133-51f964aadcd2 + github.com/scaleway/scaleway-sdk-go v1.0.0-beta.5.0.20200130170711-05d27d10a3b8 github.com/stretchr/testify v1.3.0 golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 diff --git a/go.sum b/go.sum index 2e53d9518e..8a55255d23 100644 --- a/go.sum +++ b/go.sum @@ -181,8 +181,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.1 h1:LrvDIY//XNo65Lq84G/akBuMGlawHvGBABv8f/ZN6DI= github.com/posener/complete v1.2.1/go.mod h1:6gapUrK/U1TAN7ciCoNRIdVC5sbdBTUh1DKN0g6uH7E= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.5.0.20200114152133-51f964aadcd2 h1:JDlvlTHI+2rn0amYbT28bH9eVbbKKRPLyHgZOGu2kLs= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.5.0.20200114152133-51f964aadcd2/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.5.0.20200130170711-05d27d10a3b8 h1:+y+U0MHG110iL4TkTKEb3Wh07OK7ALY2XbNFxeAEb80= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.5.0.20200130170711-05d27d10a3b8/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= diff --git a/scaleway/helpers_registry.go b/scaleway/helpers_registry.go new file mode 100644 index 0000000000..c33a56f655 --- /dev/null +++ b/scaleway/helpers_registry.go @@ -0,0 +1,25 @@ +package scaleway + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/scaleway/scaleway-sdk-go/api/registry/v1" + "github.com/scaleway/scaleway-sdk-go/scw" +) + +// registryNamespaceAPIWithRegion returns a new container registry API and the region. +func registryNamespaceAPIWithRegion(d *schema.ResourceData, m interface{}) (*registry.API, scw.Region, error) { + meta := m.(*Meta) + api := registry.NewAPI(meta.scwClient) + + region, err := extractRegion(d, meta) + return api, region, err +} + +// registryNamespaceAPIWithRegionAndID returns a new container registry API, region and ID. +func registryNamespaceAPIWithRegionAndID(m interface{}, id string) (*registry.API, scw.Region, string, error) { + meta := m.(*Meta) + api := registry.NewAPI(meta.scwClient) + + region, id, err := parseRegionalID(id) + return api, region, id, err +} diff --git a/scaleway/provider.go b/scaleway/provider.go index 93deec5921..458942bb8a 100644 --- a/scaleway/provider.go +++ b/scaleway/provider.go @@ -213,6 +213,7 @@ func Provider() terraform.ResourceProvider { "scaleway_security_group_rule": resourceScalewaySecurityGroupRule(), "scaleway_volume": resourceScalewayVolume(), "scaleway_volume_attachment": resourceScalewayVolumeAttachment(), + "scaleway_registry_namespace_beta": resourceScalewayRegistryNamespaceBeta(), }, DataSourcesMap: map[string]*schema.Resource{ diff --git a/scaleway/resource_registry_namespace_beta.go b/scaleway/resource_registry_namespace_beta.go new file mode 100644 index 0000000000..12125d191a --- /dev/null +++ b/scaleway/resource_registry_namespace_beta.go @@ -0,0 +1,134 @@ +package scaleway + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/scaleway/scaleway-sdk-go/api/registry/v1" + "github.com/scaleway/scaleway-sdk-go/scw" +) + +func resourceScalewayRegistryNamespaceBeta() *schema.Resource { + return &schema.Resource{ + Create: resourceScalewayRegistryNamespaceBetaCreate, + Read: resourceScalewayRegistryNamespaceBetaRead, + Update: resourceScalewayRegistryNamespaceBetaUpdate, + Delete: resourceScalewayRegistryNamespaceBetaDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + SchemaVersion: 0, + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The name of the container registry namespace", + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: "The description of the container registry namespace", + }, + "is_public": { + Type: schema.TypeBool, + Optional: true, + Description: "Define the default visibity policy", + }, + "endpoint": { + Type: schema.TypeString, + Computed: true, + Description: "The endpoint reachable by docker", + }, + "region": regionSchema(), + "organization_id": organizationIDSchema(), + }, + } +} + +func resourceScalewayRegistryNamespaceBetaCreate(d *schema.ResourceData, m interface{}) error { + api, region, err := registryNamespaceAPIWithRegion(d, m) + if err != nil { + return err + } + + ns, err := api.CreateNamespace(®istry.CreateNamespaceRequest{ + Region: region, + OrganizationID: d.Get("organization_id").(string), + Name: d.Get("name").(string), + Description: d.Get("description").(string), + IsPublic: d.Get("is_public").(bool), + }) + if err != nil { + return err + } + + d.SetId(newRegionalId(region, ns.ID)) + + return resourceScalewayRegistryNamespaceBetaRead(d, m) +} + +func resourceScalewayRegistryNamespaceBetaRead(d *schema.ResourceData, m interface{}) error { + api, region, id, err := registryNamespaceAPIWithRegionAndID(m, d.Id()) + if err != nil { + return err + } + + ns, err := api.GetNamespace(®istry.GetNamespaceRequest{ + Region: region, + NamespaceID: id, + }) + + if err != nil { + if is404Error(err) { + d.SetId("") + return nil + } + return err + } + + d.Set("name", ns.Name) + d.Set("description", ns.Description) + d.Set("organization_id", ns.OrganizationID) + d.Set("is_public", ns.IsPublic) + d.Set("endpoint", ns.Endpoint) + d.Set("region", ns.Region) + + return nil +} + +func resourceScalewayRegistryNamespaceBetaUpdate(d *schema.ResourceData, m interface{}) error { + api, region, id, err := registryNamespaceAPIWithRegionAndID(m, d.Id()) + if err != nil { + return err + } + + if d.HasChange("description") || d.HasChange("is_public") { + if _, err := api.UpdateNamespace(®istry.UpdateNamespaceRequest{ + Region: region, + NamespaceID: id, + Description: scw.StringPtr(d.Get("description").(string)), + IsPublic: scw.BoolPtr(d.Get("is_public").(bool)), + }); err != nil { + return err + } + } + + return resourceScalewayRegistryNamespaceBetaRead(d, m) +} + +func resourceScalewayRegistryNamespaceBetaDelete(d *schema.ResourceData, m interface{}) error { + api, region, id, err := registryNamespaceAPIWithRegionAndID(m, d.Id()) + if err != nil { + return err + } + + _, err = api.DeleteNamespace(®istry.DeleteNamespaceRequest{ + Region: region, + NamespaceID: id, + }) + + if err != nil && !is404Error(err) { + return err + } + + return nil +} diff --git a/scaleway/resource_registry_namespace_beta_test.go b/scaleway/resource_registry_namespace_beta_test.go new file mode 100644 index 0000000000..20f57d0a6c --- /dev/null +++ b/scaleway/resource_registry_namespace_beta_test.go @@ -0,0 +1,100 @@ +package scaleway + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/scaleway/scaleway-sdk-go/api/registry/v1" +) + +func TestRegistryNamespaceBeta(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckScalewayRegistryNamespaceBetaDestroy, + Steps: []resource.TestStep{ + { + Config: ` + resource scaleway_registry_namespace_beta cr01 { + name = "test-cr" + } + `, + Check: resource.ComposeTestCheckFunc( + testAccCheckScalewayRegistryNamespaceBetaExists("scaleway_registry_namespace_beta.cr01"), + resource.TestCheckResourceAttr("scaleway_registry_namespace_beta.cr01", "name", "test-cr"), + testCheckResourceAttrUUID("scaleway_registry_namespace_beta.cr01", "id"), + ), + }, + { + Config: ` + resource scaleway_registry_namespace_beta cr01 { + name = "test-cr" + description = "test registry namespace" + is_public = true + } + `, + Check: resource.ComposeTestCheckFunc( + testAccCheckScalewayRegistryNamespaceBetaExists("scaleway_registry_namespace_beta.cr01"), + resource.TestCheckResourceAttr("scaleway_registry_namespace_beta.cr01", "description", "test registry namespace"), + resource.TestCheckResourceAttr("scaleway_registry_namespace_beta.cr01", "is_public", "true"), + testCheckResourceAttrUUID("scaleway_registry_namespace_beta.cr01", "id"), + ), + }, + }, + }) +} + +func testAccCheckScalewayRegistryNamespaceBetaExists(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("resource not found: %s", n) + } + + api, region, id, err := registryNamespaceAPIWithRegionAndID(testAccProvider.Meta(), rs.Primary.ID) + if err != nil { + return nil + } + + _, err = api.GetNamespace(®istry.GetNamespaceRequest{ + NamespaceID: id, + Region: region, + }) + + if err != nil { + return err + } + + return nil + } +} + +func testAccCheckScalewayRegistryNamespaceBetaDestroy(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "scaleway_registry_namespace_beta" { + continue + } + + api, region, id, err := registryNamespaceAPIWithRegionAndID(testAccProvider.Meta(), rs.Primary.ID) + if err != nil { + return err + } + + _, err = api.DeleteNamespace(®istry.DeleteNamespaceRequest{ + NamespaceID: id, + Region: region, + }) + + if err == nil { + return fmt.Errorf("namespace (%s) still exists", rs.Primary.ID) + } + + if !is404Error(err) { + return err + } + } + + return nil +} diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/api/baremetal/v1alpha1/baremetal_sdk.go b/vendor/github.com/scaleway/scaleway-sdk-go/api/baremetal/v1alpha1/baremetal_sdk.go index b51b9d8c56..fdb571a199 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/api/baremetal/v1alpha1/baremetal_sdk.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/api/baremetal/v1alpha1/baremetal_sdk.go @@ -581,6 +581,12 @@ type Disk struct { Type string `json:"type"` } +// GetServerMetricsResponse get server metrics response +type GetServerMetricsResponse struct { + // Pings timeseries of ping on the server + Pings *scw.TimeSeries `json:"pings"` +} + // IP ip type IP struct { // ID iD of the IP @@ -637,6 +643,8 @@ type IPFailover struct { ReverseStatus IPReverseStatus `json:"reverse_status"` // ReverseStatusMessage a message related to the reverse status, in case of an error for example ReverseStatusMessage *string `json:"reverse_status_message"` + // Zone the zone in which is the ip + Zone scw.Zone `json:"zone"` } // IPFailoverEvent ip failover event @@ -800,6 +808,8 @@ type Server struct { // // Default value: normal BootType ServerBootType `json:"boot_type"` + // Zone the zone in which is the server + Zone scw.Zone `json:"zone"` } // ServerEvent server event @@ -1110,6 +1120,46 @@ func (s *API) InstallServer(req *InstallServerRequest, opts ...scw.RequestOption return &resp, nil } +type GetServerMetricsRequest struct { + Zone scw.Zone `json:"-"` + // ServerID server ID to get the metrics + ServerID string `json:"-"` +} + +// GetServerMetrics return server metrics +// +// Give the ping status on the server associated with the given ID. +func (s *API) GetServerMetrics(req *GetServerMetricsRequest, opts ...scw.RequestOption) (*GetServerMetricsResponse, error) { + var err error + + if req.Zone == "" { + defaultZone, _ := s.client.GetDefaultZone() + req.Zone = defaultZone + } + + if fmt.Sprint(req.Zone) == "" { + return nil, errors.New("field Zone cannot be empty in request") + } + + if fmt.Sprint(req.ServerID) == "" { + return nil, errors.New("field ServerID cannot be empty in request") + } + + scwReq := &scw.ScalewayRequest{ + Method: "GET", + Path: "/baremetal/v1alpha1/zones/" + fmt.Sprint(req.Zone) + "/servers/" + fmt.Sprint(req.ServerID) + "/metrics", + Headers: http.Header{}, + } + + var resp GetServerMetricsResponse + + err = s.client.Do(scwReq, &resp, opts...) + if err != nil { + return nil, err + } + return &resp, nil +} + type DeleteServerRequest struct { Zone scw.Zone `json:"-"` // ServerID iD of the server to delete diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/api/baremetal/v1alpha1/server_utils.go b/vendor/github.com/scaleway/scaleway-sdk-go/api/baremetal/v1alpha1/server_utils.go index e4b74e3e2e..752574a45f 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/api/baremetal/v1alpha1/server_utils.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/api/baremetal/v1alpha1/server_utils.go @@ -27,17 +27,17 @@ func (s *API) WaitForServer(req *WaitForServerRequest) (*Server, error) { } server, err := async.WaitSync(&async.WaitSyncConfig{ - Get: func() (interface{}, error, bool) { + Get: func() (interface{}, bool, error) { res, err := s.GetServer(&GetServerRequest{ ServerID: req.ServerID, Zone: req.Zone, }) if err != nil { - return nil, err, false + return nil, false, err } _, isTerminal := terminalStatus[res.Status] - return res, err, isTerminal + return res, isTerminal, err }, Timeout: req.Timeout, IntervalStrategy: async.LinearIntervalStrategy(5 * time.Second), @@ -67,21 +67,21 @@ func (s *API) WaitForServerInstall(req *WaitForServerInstallRequest) (*Server, e } server, err := async.WaitSync(&async.WaitSyncConfig{ - Get: func() (interface{}, error, bool) { + Get: func() (interface{}, bool, error) { res, err := s.GetServer(&GetServerRequest{ ServerID: req.ServerID, Zone: req.Zone, }) if err != nil { - return nil, err, false + return nil, false, err } if res.Install == nil { - return nil, errors.New("server creation has not begun for server %s", req.ServerID), false + return nil, false, errors.New("server creation has not begun for server %s", req.ServerID) } _, isTerminal := installTerminalStatus[res.Install.Status] - return res, err, isTerminal + return res, isTerminal, err }, Timeout: req.Timeout, IntervalStrategy: async.LinearIntervalStrategy(15 * time.Second), diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/api/instance/v1/server_utils.go b/vendor/github.com/scaleway/scaleway-sdk-go/api/instance/v1/server_utils.go index cd730d7ec8..66c3529394 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/api/instance/v1/server_utils.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/api/instance/v1/server_utils.go @@ -14,13 +14,21 @@ import ( "github.com/scaleway/scaleway-sdk-go/validation" ) +const ( + defaultTimeout = 5 * time.Minute + defaultRetryInterval = 5 * time.Second +) + +var ( + RetryInterval = defaultRetryInterval +) + // CreateServer creates a server. func (s *API) CreateServer(req *CreateServerRequest, opts ...scw.RequestOption) (*CreateServerResponse, error) { - // If image is not a UUID we try to fetch it from marketplace. if req.Image != "" && !validation.IsUUID(req.Image) { apiMarketplace := marketplace.NewAPI(s.client) - imageId, err := apiMarketplace.GetLocalImageIDByLabel(&marketplace.GetLocalImageIDByLabelRequest{ + imageID, err := apiMarketplace.GetLocalImageIDByLabel(&marketplace.GetLocalImageIDByLabelRequest{ ImageLabel: req.Image, Zone: req.Zone, CommercialType: req.CommercialType, @@ -28,10 +36,10 @@ func (s *API) CreateServer(req *CreateServerRequest, opts ...scw.RequestOption) if err != nil { return nil, err } - req.Image = imageId + req.Image = imageID } - return s.createServer((*CreateServerRequest)(req), opts...) + return s.createServer(req, opts...) } // UpdateServer updates a server. @@ -39,7 +47,7 @@ func (s *API) CreateServer(req *CreateServerRequest, opts ...scw.RequestOption) // Note: Implementation is thread-safe. func (s *API) UpdateServer(req *UpdateServerRequest, opts ...scw.RequestOption) (*UpdateServerResponse, error) { defer lockServer(req.Zone, req.ServerID).Unlock() - return s.updateServer((*UpdateServerRequest)(req), opts...) + return s.updateServer(req, opts...) } // WaitForServerRequest is used by WaitForServer method. @@ -52,7 +60,6 @@ type WaitForServerRequest struct { // WaitForServer wait for the server to be in a "terminal state" before returning. // This function can be used to wait for a server to be started for example. func (s *API) WaitForServer(req *WaitForServerRequest) (*Server, error) { - terminalStatus := map[ServerState]struct{}{ ServerStateStopped: {}, ServerStateStoppedInPlace: {}, @@ -61,21 +68,21 @@ func (s *API) WaitForServer(req *WaitForServerRequest) (*Server, error) { } server, err := async.WaitSync(&async.WaitSyncConfig{ - Get: func() (interface{}, error, bool) { + Get: func() (interface{}, bool, error) { res, err := s.GetServer(&GetServerRequest{ ServerID: req.ServerID, Zone: req.Zone, }) if err != nil { - return nil, err, false + return nil, false, err } _, isTerminal := terminalStatus[res.Server.State] - return res.Server, err, isTerminal + return res.Server, isTerminal, err }, Timeout: req.Timeout, - IntervalStrategy: async.LinearIntervalStrategy(5 * time.Second), + IntervalStrategy: async.LinearIntervalStrategy(RetryInterval), }) if err != nil { return nil, errors.Wrap(err, "waiting for server failed") @@ -97,7 +104,7 @@ type ServerActionAndWaitRequest struct { // expected by this action. func (s *API) ServerActionAndWait(req *ServerActionAndWaitRequest) error { if req.Timeout == 0 { - req.Timeout = 5 * time.Minute + req.Timeout = defaultTimeout } _, err := s.ServerAction(&ServerActionRequest{ @@ -145,7 +152,6 @@ type GetServerTypeRequest struct { // GetServerType get server type info by it's name. func (s *API) GetServerType(req *GetServerTypeRequest) (*ServerType, error) { - res, err := s.ListServersTypes(&ListServersTypesRequest{ Zone: req.Zone, }, scw.WithAllPages()) diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/api/k8s/v1beta4/k8s_helpers.go b/vendor/github.com/scaleway/scaleway-sdk-go/api/k8s/v1beta4/k8s_helpers.go index ffdaf4572e..66ae31d87c 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/api/k8s/v1beta4/k8s_helpers.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/api/k8s/v1beta4/k8s_helpers.go @@ -27,17 +27,17 @@ func (s *API) WaitForCluster(req *WaitForClusterRequest) (*Cluster, error) { } cluster, err := async.WaitSync(&async.WaitSyncConfig{ - Get: func() (interface{}, error, bool) { + Get: func() (interface{}, bool, error) { cluster, err := s.GetCluster(&GetClusterRequest{ ClusterID: req.ClusterID, Region: req.Region, }) if err != nil { - return nil, err, false + return nil, false, err } _, isTerminal := terminalStatus[cluster.Status] - return cluster, nil, isTerminal + return cluster, isTerminal, nil }, Timeout: req.Timeout, IntervalStrategy: async.LinearIntervalStrategy(5 * time.Second), diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/api/lb/v1/lb_sdk.go b/vendor/github.com/scaleway/scaleway-sdk-go/api/lb/v1/lb_sdk.go index 8a7eb393ae..c4effc5799 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/api/lb/v1/lb_sdk.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/api/lb/v1/lb_sdk.go @@ -685,6 +685,56 @@ func (enum *Protocol) UnmarshalJSON(data []byte) error { return nil } +// ProxyProtocol pROXY protocol, forward client's address (must be supported by backend servers software) +// +// The PROXY protocol informs the other end about the incoming connection, so that it can know the client's address or the public address it accessed to, whatever the upper layer protocol. +// +// * `proxy_protocol_none` Disable proxy protocol. +// * `proxy_protocol_v1` Version one (text format). +// * `proxy_protocol_v2` Version two (binary format). +// * `proxy_protocol_v2_ssl` Version two with SSL connection. +// * `proxy_protocol_v2_ssl_cn` Version two with SSL connection and common name information. +// +type ProxyProtocol string + +const ( + // ProxyProtocolProxyProtocolUnknown is [insert doc]. + ProxyProtocolProxyProtocolUnknown = ProxyProtocol("proxy_protocol_unknown") + // ProxyProtocolProxyProtocolNone is [insert doc]. + ProxyProtocolProxyProtocolNone = ProxyProtocol("proxy_protocol_none") + // ProxyProtocolProxyProtocolV1 is [insert doc]. + ProxyProtocolProxyProtocolV1 = ProxyProtocol("proxy_protocol_v1") + // ProxyProtocolProxyProtocolV2 is [insert doc]. + ProxyProtocolProxyProtocolV2 = ProxyProtocol("proxy_protocol_v2") + // ProxyProtocolProxyProtocolV2Ssl is [insert doc]. + ProxyProtocolProxyProtocolV2Ssl = ProxyProtocol("proxy_protocol_v2_ssl") + // ProxyProtocolProxyProtocolV2SslCn is [insert doc]. + ProxyProtocolProxyProtocolV2SslCn = ProxyProtocol("proxy_protocol_v2_ssl_cn") +) + +func (enum ProxyProtocol) String() string { + if enum == "" { + // return default value if empty + return "proxy_protocol_unknown" + } + return string(enum) +} + +func (enum ProxyProtocol) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf(`"%s"`, enum)), nil +} + +func (enum *ProxyProtocol) UnmarshalJSON(data []byte) error { + tmp := "" + + if err := json.Unmarshal(data, &tmp); err != nil { + return err + } + + *enum = ProxyProtocol(ProxyProtocol(tmp).String()) + return nil +} + type StickySessionsType string const ( @@ -796,6 +846,10 @@ type Backend struct { // // Default value: on_marked_down_action_none OnMarkedDownAction OnMarkedDownAction `json:"on_marked_down_action"` + // ProxyProtocol + // + // Default value: proxy_protocol_unknown + ProxyProtocol ProxyProtocol `json:"proxy_protocol"` } func (m *Backend) UnmarshalJSON(b []byte) error { @@ -1846,7 +1900,7 @@ type CreateBackendRequest struct { HealthCheck *HealthCheck `json:"health_check"` // ServerIP backend server IP addresses list (IPv4 or IPv6) ServerIP []string `json:"server_ip"` - // SendProxyV2 enables PROXY protocol version 2 (must be supported by backend servers) + // SendProxyV2 deprecated in favor of proxy_protocol field ! SendProxyV2 bool `json:"send_proxy_v2"` // TimeoutServer maximum server connection inactivity time TimeoutServer *time.Duration `json:"timeout_server"` @@ -1858,6 +1912,18 @@ type CreateBackendRequest struct { // // Default value: on_marked_down_action_none OnMarkedDownAction OnMarkedDownAction `json:"on_marked_down_action"` + // ProxyProtocol pROXY protocol, forward client's address (must be supported by backend servers software) + // + // The PROXY protocol informs the other end about the incoming connection, so that it can know the client's address or the public address it accessed to, whatever the upper layer protocol. + // + // * `proxy_protocol_none` Disable proxy protocol. + // * `proxy_protocol_v1` Version one (text format). + // * `proxy_protocol_v2` Version two (binary format). + // * `proxy_protocol_v2_ssl` Version two with SSL connection. + // * `proxy_protocol_v2_ssl_cn` Version two with SSL connection and common name information. + // + // Default value: proxy_protocol_unknown + ProxyProtocol ProxyProtocol `json:"proxy_protocol"` } func (m *CreateBackendRequest) UnmarshalJSON(b []byte) error { @@ -1975,38 +2041,42 @@ func (s *API) GetBackend(req *GetBackendRequest, opts ...scw.RequestOption) (*Ba type UpdateBackendRequest struct { Region scw.Region `json:"-"` - // BackendID backend ID to update + BackendID string `json:"-"` - // Name resource name + Name string `json:"name"` - // ForwardProtocol backend protocol. TCP or HTTP + // ForwardProtocol // // Default value: tcp ForwardProtocol Protocol `json:"forward_protocol"` - // ForwardPort user sessions will be forwarded to this port of backend servers + ForwardPort int32 `json:"forward_port"` - // ForwardPortAlgorithm load balancing algorithm + // ForwardPortAlgorithm // // Default value: roundrobin ForwardPortAlgorithm ForwardPortAlgorithm `json:"forward_port_algorithm"` - // StickySessions enable cookie-based session persistence + // StickySessions // // Default value: none StickySessions StickySessionsType `json:"sticky_sessions"` - // StickySessionsCookieName cookie name for for sticky sessions + StickySessionsCookieName string `json:"sticky_sessions_cookie_name"` - // SendProxyV2 enables PROXY protocol version 2 (must be supported by backend servers) + SendProxyV2 bool `json:"send_proxy_v2"` - // TimeoutServer maximum server connection inactivity time + TimeoutServer *time.Duration `json:"timeout_server"` - // TimeoutConnect maximum initial server connection establishment time + TimeoutConnect *time.Duration `json:"timeout_connect"` - // TimeoutTunnel maximum tunnel inactivity time + TimeoutTunnel *time.Duration `json:"timeout_tunnel"` - // OnMarkedDownAction modify what occurs when a backend server is marked down + // OnMarkedDownAction // // Default value: on_marked_down_action_none OnMarkedDownAction OnMarkedDownAction `json:"on_marked_down_action"` + // ProxyProtocol + // + // Default value: proxy_protocol_unknown + ProxyProtocol ProxyProtocol `json:"proxy_protocol"` } func (m *UpdateBackendRequest) UnmarshalJSON(b []byte) error { diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/api/lb/v1/lb_utils.go b/vendor/github.com/scaleway/scaleway-sdk-go/api/lb/v1/lb_utils.go index cfdbaaf3e5..6e5d60a72f 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/api/lb/v1/lb_utils.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/api/lb/v1/lb_utils.go @@ -18,7 +18,6 @@ type WaitForLbRequest struct { // WaitForLb waits for the lb to be in a "terminal state" before returning. // This function can be used to wait for a lb to be ready for example. func (s *API) WaitForLb(req *WaitForLbRequest) (*Lb, error) { - terminalStatus := map[LbStatus]struct{}{ LbStatusReady: {}, LbStatusStopped: {}, @@ -27,18 +26,18 @@ func (s *API) WaitForLb(req *WaitForLbRequest) (*Lb, error) { } lb, err := async.WaitSync(&async.WaitSyncConfig{ - Get: func() (interface{}, error, bool) { + Get: func() (interface{}, bool, error) { res, err := s.GetLb(&GetLbRequest{ LbID: req.LbID, Region: req.Region, }) if err != nil { - return nil, err, false + return nil, false, err } _, isTerminal := terminalStatus[res.Status] - return res, nil, isTerminal + return res, isTerminal, nil }, Timeout: req.Timeout, IntervalStrategy: async.LinearIntervalStrategy(5 * time.Second), diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/api/marketplace/v1/marketplace_utils.go b/vendor/github.com/scaleway/scaleway-sdk-go/api/marketplace/v1/marketplace_utils.go index 12512c35c1..2d78bb2664 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/api/marketplace/v1/marketplace_utils.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/api/marketplace/v1/marketplace_utils.go @@ -11,9 +11,7 @@ import ( // getLocalImage returns the correct local version of an image matching // the current zone and the compatible commercial type func (version *Version) getLocalImage(zone scw.Zone, commercialType string) (*LocalImage, error) { - for _, localImage := range version.LocalImages { - // Check if in correct zone if localImage.Zone != zone { continue @@ -28,13 +26,11 @@ func (version *Version) getLocalImage(zone scw.Zone, commercialType string) (*Lo } return nil, fmt.Errorf("couldn't find compatible local image for this image version (%s)", version.ID) - } // getLatestVersion returns the current/latests version on an image, // or an error in case the image doesn't have a public version. func (image *Image) getLatestVersion() (*Version, error) { - for _, version := range image.Versions { if version.ID == image.CurrentPublicVersion { return version, nil @@ -54,7 +50,6 @@ type GetLocalImageIDByLabelRequest struct { // GetLocalImageIDByLabel search for an image with the given label (exact match) in the given region // it returns the latest version of this specific image. func (s *API) GetLocalImageIDByLabel(req *GetLocalImageIDByLabelRequest) (string, error) { - if req.Zone == "" { defaultZone, _ := s.client.GetDefaultZone() req.Zone = defaultZone @@ -71,10 +66,8 @@ func (s *API) GetLocalImageIDByLabel(req *GetLocalImageIDByLabelRequest) (string commercialType := strings.ToUpper(req.CommercialType) for _, image := range images { - // Match label of the image if label == image.Label { - latestVersion, err := image.getLatestVersion() if err != nil { return "", errors.Wrap(err, "couldn't find a matching image for the given label (%s), zone (%s) and commercial type (%s)", req.ImageLabel, req.Zone, req.CommercialType) @@ -87,7 +80,6 @@ func (s *API) GetLocalImageIDByLabel(req *GetLocalImageIDByLabelRequest) (string return localImage.ID, nil } - } return "", errors.New("couldn't find a matching image for the given label (%s), zone (%s) and commercial type (%s)", req.ImageLabel, req.Zone, req.CommercialType) diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/api/rdb/v1/rdb_sdk.go b/vendor/github.com/scaleway/scaleway-sdk-go/api/rdb/v1/rdb_sdk.go index 8681ddafa0..ad205050f9 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/api/rdb/v1/rdb_sdk.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/api/rdb/v1/rdb_sdk.go @@ -162,6 +162,8 @@ const ( DatabaseBackupStatusDeleting = DatabaseBackupStatus("deleting") // DatabaseBackupStatusError is [insert doc]. DatabaseBackupStatusError = DatabaseBackupStatus("error") + // DatabaseBackupStatusExporting is [insert doc]. + DatabaseBackupStatusExporting = DatabaseBackupStatus("exporting") ) func (enum DatabaseBackupStatus) String() string { @@ -714,6 +716,10 @@ type DatabaseBackup struct { InstanceName string `json:"instance_name"` + DownloadURL *string `json:"download_url"` + + DownloadURLExpiresAt time.Time `json:"download_url_expires_at"` + Region scw.Region `json:"region"` } @@ -1295,6 +1301,48 @@ func (s *API) RestoreDatabaseBackup(req *RestoreDatabaseBackupRequest, opts ...s return &resp, nil } +type ExportDatabaseBackupRequest struct { + Region scw.Region `json:"-"` + + DatabaseBackupID string `json:"-"` +} + +func (s *API) ExportDatabaseBackup(req *ExportDatabaseBackupRequest, opts ...scw.RequestOption) (*DatabaseBackup, error) { + var err error + + if req.Region == "" { + defaultRegion, _ := s.client.GetDefaultRegion() + req.Region = defaultRegion + } + + if fmt.Sprint(req.Region) == "" { + return nil, errors.New("field Region cannot be empty in request") + } + + if fmt.Sprint(req.DatabaseBackupID) == "" { + return nil, errors.New("field DatabaseBackupID cannot be empty in request") + } + + scwReq := &scw.ScalewayRequest{ + Method: "POST", + Path: "/rdb/v1/regions/" + fmt.Sprint(req.Region) + "/backups/" + fmt.Sprint(req.DatabaseBackupID) + "/export", + Headers: http.Header{}, + } + + err = scwReq.SetBody(req) + if err != nil { + return nil, err + } + + var resp DatabaseBackup + + err = s.client.Do(scwReq, &resp, opts...) + if err != nil { + return nil, err + } + return &resp, nil +} + type CloneInstanceRequest struct { Region scw.Region `json:"-"` diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/api/rdb/v1/rdb_utils.go b/vendor/github.com/scaleway/scaleway-sdk-go/api/rdb/v1/rdb_utils.go index bde0100151..ce97648efb 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/api/rdb/v1/rdb_utils.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/api/rdb/v1/rdb_utils.go @@ -18,7 +18,6 @@ type WaitForInstanceRequest struct { // WaitForInstance waits for the instance to be in a "terminal state" before returning. // This function can be used to wait for an instance to be ready for example. func (s *API) WaitForInstance(req *WaitForInstanceRequest) (*Instance, error) { - terminalStatus := map[InstanceStatus]struct{}{ InstanceStatusReady: {}, InstanceStatusDiskFull: {}, @@ -26,18 +25,18 @@ func (s *API) WaitForInstance(req *WaitForInstanceRequest) (*Instance, error) { } instance, err := async.WaitSync(&async.WaitSyncConfig{ - Get: func() (interface{}, error, bool) { + Get: func() (interface{}, bool, error) { res, err := s.GetInstance(&GetInstanceRequest{ InstanceID: req.InstanceID, Region: req.Region, }) if err != nil { - return nil, err, false + return nil, false, err } _, isTerminal := terminalStatus[res.Status] - return res, nil, isTerminal + return res, isTerminal, nil }, Timeout: req.Timeout, IntervalStrategy: async.LinearIntervalStrategy(5 * time.Second), diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/api/registry/v1/registry_sdk.go b/vendor/github.com/scaleway/scaleway-sdk-go/api/registry/v1/registry_sdk.go new file mode 100644 index 0000000000..b87cde02d1 --- /dev/null +++ b/vendor/github.com/scaleway/scaleway-sdk-go/api/registry/v1/registry_sdk.go @@ -0,0 +1,1048 @@ +// This file was automatically generated. DO NOT EDIT. +// If you have any remark or suggestion do not hesitate to open an issue. + +// Package registry provides methods and message types of the registry v1 API. +package registry + +import ( + "bytes" + "encoding/json" + "fmt" + "net" + "net/http" + "net/url" + "time" + + "github.com/scaleway/scaleway-sdk-go/internal/errors" + "github.com/scaleway/scaleway-sdk-go/internal/marshaler" + "github.com/scaleway/scaleway-sdk-go/internal/parameter" + "github.com/scaleway/scaleway-sdk-go/namegenerator" + "github.com/scaleway/scaleway-sdk-go/scw" +) + +// always import dependencies +var ( + _ fmt.Stringer + _ json.Unmarshaler + _ url.URL + _ net.IP + _ http.Header + _ bytes.Reader + _ time.Time + + _ scw.ScalewayRequest + _ marshaler.Duration + _ scw.File + _ = parameter.AddToQuery + _ = namegenerator.GetRandomName +) + +// API docker registry API +type API struct { + client *scw.Client +} + +// NewAPI returns a API object from a Scaleway client. +func NewAPI(client *scw.Client) *API { + return &API{ + client: client, + } +} + +type ImageStatus string + +const ( + // ImageStatusUnknown is [insert doc]. + ImageStatusUnknown = ImageStatus("unknown") + // ImageStatusReady is [insert doc]. + ImageStatusReady = ImageStatus("ready") + // ImageStatusDeleting is [insert doc]. + ImageStatusDeleting = ImageStatus("deleting") + // ImageStatusError is [insert doc]. + ImageStatusError = ImageStatus("error") + // ImageStatusLocked is [insert doc]. + ImageStatusLocked = ImageStatus("locked") +) + +func (enum ImageStatus) String() string { + if enum == "" { + // return default value if empty + return "unknown" + } + return string(enum) +} + +func (enum ImageStatus) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf(`"%s"`, enum)), nil +} + +func (enum *ImageStatus) UnmarshalJSON(data []byte) error { + tmp := "" + + if err := json.Unmarshal(data, &tmp); err != nil { + return err + } + + *enum = ImageStatus(ImageStatus(tmp).String()) + return nil +} + +type ImageVisibility string + +const ( + // ImageVisibilityVisibilityUnknown is [insert doc]. + ImageVisibilityVisibilityUnknown = ImageVisibility("visibility_unknown") + // ImageVisibilityInherit is [insert doc]. + ImageVisibilityInherit = ImageVisibility("inherit") + // ImageVisibilityPublic is [insert doc]. + ImageVisibilityPublic = ImageVisibility("public") + // ImageVisibilityPrivate is [insert doc]. + ImageVisibilityPrivate = ImageVisibility("private") +) + +func (enum ImageVisibility) String() string { + if enum == "" { + // return default value if empty + return "visibility_unknown" + } + return string(enum) +} + +func (enum ImageVisibility) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf(`"%s"`, enum)), nil +} + +func (enum *ImageVisibility) UnmarshalJSON(data []byte) error { + tmp := "" + + if err := json.Unmarshal(data, &tmp); err != nil { + return err + } + + *enum = ImageVisibility(ImageVisibility(tmp).String()) + return nil +} + +type ListImagesRequestOrderBy string + +const ( + // ListImagesRequestOrderByCreatedAtAsc is [insert doc]. + ListImagesRequestOrderByCreatedAtAsc = ListImagesRequestOrderBy("created_at_asc") + // ListImagesRequestOrderByCreatedAtDesc is [insert doc]. + ListImagesRequestOrderByCreatedAtDesc = ListImagesRequestOrderBy("created_at_desc") + // ListImagesRequestOrderByNameAsc is [insert doc]. + ListImagesRequestOrderByNameAsc = ListImagesRequestOrderBy("name_asc") + // ListImagesRequestOrderByNameDesc is [insert doc]. + ListImagesRequestOrderByNameDesc = ListImagesRequestOrderBy("name_desc") +) + +func (enum ListImagesRequestOrderBy) String() string { + if enum == "" { + // return default value if empty + return "created_at_asc" + } + return string(enum) +} + +func (enum ListImagesRequestOrderBy) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf(`"%s"`, enum)), nil +} + +func (enum *ListImagesRequestOrderBy) UnmarshalJSON(data []byte) error { + tmp := "" + + if err := json.Unmarshal(data, &tmp); err != nil { + return err + } + + *enum = ListImagesRequestOrderBy(ListImagesRequestOrderBy(tmp).String()) + return nil +} + +type ListNamespacesRequestOrderBy string + +const ( + // ListNamespacesRequestOrderByCreatedAtAsc is [insert doc]. + ListNamespacesRequestOrderByCreatedAtAsc = ListNamespacesRequestOrderBy("created_at_asc") + // ListNamespacesRequestOrderByCreatedAtDesc is [insert doc]. + ListNamespacesRequestOrderByCreatedAtDesc = ListNamespacesRequestOrderBy("created_at_desc") + // ListNamespacesRequestOrderByDescriptionAsc is [insert doc]. + ListNamespacesRequestOrderByDescriptionAsc = ListNamespacesRequestOrderBy("description_asc") + // ListNamespacesRequestOrderByDescriptionDesc is [insert doc]. + ListNamespacesRequestOrderByDescriptionDesc = ListNamespacesRequestOrderBy("description_desc") + // ListNamespacesRequestOrderByNameAsc is [insert doc]. + ListNamespacesRequestOrderByNameAsc = ListNamespacesRequestOrderBy("name_asc") + // ListNamespacesRequestOrderByNameDesc is [insert doc]. + ListNamespacesRequestOrderByNameDesc = ListNamespacesRequestOrderBy("name_desc") +) + +func (enum ListNamespacesRequestOrderBy) String() string { + if enum == "" { + // return default value if empty + return "created_at_asc" + } + return string(enum) +} + +func (enum ListNamespacesRequestOrderBy) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf(`"%s"`, enum)), nil +} + +func (enum *ListNamespacesRequestOrderBy) UnmarshalJSON(data []byte) error { + tmp := "" + + if err := json.Unmarshal(data, &tmp); err != nil { + return err + } + + *enum = ListNamespacesRequestOrderBy(ListNamespacesRequestOrderBy(tmp).String()) + return nil +} + +type ListTagsRequestOrderBy string + +const ( + // ListTagsRequestOrderByCreatedAtAsc is [insert doc]. + ListTagsRequestOrderByCreatedAtAsc = ListTagsRequestOrderBy("created_at_asc") + // ListTagsRequestOrderByCreatedAtDesc is [insert doc]. + ListTagsRequestOrderByCreatedAtDesc = ListTagsRequestOrderBy("created_at_desc") + // ListTagsRequestOrderByNameAsc is [insert doc]. + ListTagsRequestOrderByNameAsc = ListTagsRequestOrderBy("name_asc") + // ListTagsRequestOrderByNameDesc is [insert doc]. + ListTagsRequestOrderByNameDesc = ListTagsRequestOrderBy("name_desc") +) + +func (enum ListTagsRequestOrderBy) String() string { + if enum == "" { + // return default value if empty + return "created_at_asc" + } + return string(enum) +} + +func (enum ListTagsRequestOrderBy) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf(`"%s"`, enum)), nil +} + +func (enum *ListTagsRequestOrderBy) UnmarshalJSON(data []byte) error { + tmp := "" + + if err := json.Unmarshal(data, &tmp); err != nil { + return err + } + + *enum = ListTagsRequestOrderBy(ListTagsRequestOrderBy(tmp).String()) + return nil +} + +type NamespaceStatus string + +const ( + // NamespaceStatusUnknown is [insert doc]. + NamespaceStatusUnknown = NamespaceStatus("unknown") + // NamespaceStatusReady is [insert doc]. + NamespaceStatusReady = NamespaceStatus("ready") + // NamespaceStatusDeleting is [insert doc]. + NamespaceStatusDeleting = NamespaceStatus("deleting") + // NamespaceStatusError is [insert doc]. + NamespaceStatusError = NamespaceStatus("error") + // NamespaceStatusLocked is [insert doc]. + NamespaceStatusLocked = NamespaceStatus("locked") +) + +func (enum NamespaceStatus) String() string { + if enum == "" { + // return default value if empty + return "unknown" + } + return string(enum) +} + +func (enum NamespaceStatus) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf(`"%s"`, enum)), nil +} + +func (enum *NamespaceStatus) UnmarshalJSON(data []byte) error { + tmp := "" + + if err := json.Unmarshal(data, &tmp); err != nil { + return err + } + + *enum = NamespaceStatus(NamespaceStatus(tmp).String()) + return nil +} + +type TagStatus string + +const ( + // TagStatusUnknown is [insert doc]. + TagStatusUnknown = TagStatus("unknown") + // TagStatusReady is [insert doc]. + TagStatusReady = TagStatus("ready") + // TagStatusDeleting is [insert doc]. + TagStatusDeleting = TagStatus("deleting") + // TagStatusError is [insert doc]. + TagStatusError = TagStatus("error") + // TagStatusLocked is [insert doc]. + TagStatusLocked = TagStatus("locked") +) + +func (enum TagStatus) String() string { + if enum == "" { + // return default value if empty + return "unknown" + } + return string(enum) +} + +func (enum TagStatus) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf(`"%s"`, enum)), nil +} + +func (enum *TagStatus) UnmarshalJSON(data []byte) error { + tmp := "" + + if err := json.Unmarshal(data, &tmp); err != nil { + return err + } + + *enum = TagStatus(TagStatus(tmp).String()) + return nil +} + +// Image image +type Image struct { + // ID the unique ID of the Image + ID string `json:"id"` + // Name the Image name, unique in a namespace + Name string `json:"name"` + // NamespaceID the unique ID of the Namespace the image belongs to + NamespaceID string `json:"namespace_id"` + // Status the status of the image + // + // Default value: unknown + Status ImageStatus `json:"status"` + // StatusMessage details of the image status + StatusMessage *string `json:"status_message"` + // Visibility a `public` image is pullable from internet without authentication, opposed to a `private` image. `inherit` will use the namespace `is_public` parameter + // + // Default value: visibility_unknown + Visibility ImageVisibility `json:"visibility"` + // Size image size in bytes, calculated from the size of image layers + // + // Image size in bytes, calculated from the size of image layers. One layer used in two tags of the same image is counted once but one layer used in two images is counted twice. + Size uint64 `json:"size"` + // CreatedAt creation date + CreatedAt time.Time `json:"created_at"` + // UpdatedAt last modification date, from the user or the service + UpdatedAt time.Time `json:"updated_at"` + // Tags list of docker tags of the image + Tags []string `json:"tags"` +} + +// ListImagesResponse list images response +type ListImagesResponse struct { + // Images paginated list of images matching filters + Images []*Image `json:"images"` + // TotalCount total number of images matching filters + TotalCount uint32 `json:"total_count"` +} + +// ListNamespacesResponse list namespaces response +type ListNamespacesResponse struct { + // Namespaces paginated list of namespaces matching filters + Namespaces []*Namespace `json:"namespaces"` + // TotalCount total number of namespaces matching filters + TotalCount uint32 `json:"total_count"` +} + +// ListTagsResponse list tags response +type ListTagsResponse struct { + // Tags paginated list of tags matching filters + Tags []*Tag `json:"tags"` + // TotalCount total number of tags matching filters + TotalCount uint32 `json:"total_count"` +} + +// Namespace namespace +type Namespace struct { + // ID the unique ID of the namespace + ID string `json:"id"` + // Name the name of the namespace, unique in a region accross all organizations + Name string `json:"name"` + // Description description of the namespace + Description string `json:"description"` + // OrganizationID owner of the namespace + OrganizationID string `json:"organization_id"` + // Status namespace status + // + // Default value: unknown + Status NamespaceStatus `json:"status"` + // StatusMessage namespace status details + StatusMessage string `json:"status_message"` + // Endpoint endpoint reachable by docker + Endpoint string `json:"endpoint"` + // IsPublic namespace visibility policy + IsPublic bool `json:"is_public"` + // Size total size of the namespace, calculated as the sum of the size of all images in the namespace + Size uint64 `json:"size"` + // CreatedAt creation date + CreatedAt time.Time `json:"created_at"` + // UpdatedAt last modification date, from the user or the service + UpdatedAt time.Time `json:"updated_at"` + // ImageCount number of images in the namespace + ImageCount uint32 `json:"image_count"` + // Region region the namespace belongs to + Region scw.Region `json:"region"` +} + +// Tag tag +type Tag struct { + // ID the unique ID of the tag + ID string `json:"id"` + // Name tag name, unique for an image + Name string `json:"name"` + // ImageID image ID this tag belongs to + ImageID string `json:"image_id"` + // Status tag status + // + // Default value: unknown + Status TagStatus `json:"status"` + // Digest hash of the tag actual content. Several tags of a same image may have the same digest + Digest string `json:"digest"` + // CreatedAt creation date + CreatedAt time.Time `json:"created_at"` + // UpdatedAt last modification date, from the user or the service + UpdatedAt time.Time `json:"updated_at"` +} + +// Service API + +type ListNamespacesRequest struct { + Region scw.Region `json:"-"` + // Page a positive integer to choose the page to display + Page *int32 `json:"-"` + // PageSize a positive integer lower or equal to 100 to select the number of items to display + PageSize *uint32 `json:"-"` + // OrderBy field by which to order the display of Images + // + // Default value: created_at_asc + OrderBy ListNamespacesRequestOrderBy `json:"-"` + // OrganizationID filter by the namespace owner + OrganizationID *string `json:"-"` + // Name filter by the namespace name (exact match) + Name *string `json:"-"` +} + +// ListNamespaces list all your namespaces +func (s *API) ListNamespaces(req *ListNamespacesRequest, opts ...scw.RequestOption) (*ListNamespacesResponse, error) { + var err error + + if req.Region == "" { + defaultRegion, _ := s.client.GetDefaultRegion() + req.Region = defaultRegion + } + + defaultPageSize, exist := s.client.GetDefaultPageSize() + if (req.PageSize == nil || *req.PageSize == 0) && exist { + req.PageSize = &defaultPageSize + } + + query := url.Values{} + parameter.AddToQuery(query, "page", req.Page) + parameter.AddToQuery(query, "page_size", req.PageSize) + parameter.AddToQuery(query, "order_by", req.OrderBy) + parameter.AddToQuery(query, "organization_id", req.OrganizationID) + parameter.AddToQuery(query, "name", req.Name) + + if fmt.Sprint(req.Region) == "" { + return nil, errors.New("field Region cannot be empty in request") + } + + scwReq := &scw.ScalewayRequest{ + Method: "GET", + Path: "/registry/v1/regions/" + fmt.Sprint(req.Region) + "/namespaces", + Query: query, + Headers: http.Header{}, + } + + var resp ListNamespacesResponse + + err = s.client.Do(scwReq, &resp, opts...) + if err != nil { + return nil, err + } + return &resp, nil +} + +// UnsafeGetTotalCount should not be used +// Internal usage only +func (r *ListNamespacesResponse) UnsafeGetTotalCount() uint32 { + return r.TotalCount +} + +// UnsafeAppend should not be used +// Internal usage only +func (r *ListNamespacesResponse) UnsafeAppend(res interface{}) (uint32, error) { + results, ok := res.(*ListNamespacesResponse) + if !ok { + return 0, errors.New("%T type cannot be appended to type %T", res, r) + } + + r.Namespaces = append(r.Namespaces, results.Namespaces...) + r.TotalCount += uint32(len(results.Namespaces)) + return uint32(len(results.Namespaces)), nil +} + +type GetNamespaceRequest struct { + Region scw.Region `json:"-"` + // NamespaceID the unique ID of the Namespace + NamespaceID string `json:"-"` +} + +// GetNamespace get a namespace +// +// Get the namespace associated with the given id. +func (s *API) GetNamespace(req *GetNamespaceRequest, opts ...scw.RequestOption) (*Namespace, error) { + var err error + + if req.Region == "" { + defaultRegion, _ := s.client.GetDefaultRegion() + req.Region = defaultRegion + } + + if fmt.Sprint(req.Region) == "" { + return nil, errors.New("field Region cannot be empty in request") + } + + if fmt.Sprint(req.NamespaceID) == "" { + return nil, errors.New("field NamespaceID cannot be empty in request") + } + + scwReq := &scw.ScalewayRequest{ + Method: "GET", + Path: "/registry/v1/regions/" + fmt.Sprint(req.Region) + "/namespaces/" + fmt.Sprint(req.NamespaceID) + "", + Headers: http.Header{}, + } + + var resp Namespace + + err = s.client.Do(scwReq, &resp, opts...) + if err != nil { + return nil, err + } + return &resp, nil +} + +type CreateNamespaceRequest struct { + Region scw.Region `json:"-"` + // Name define a namespace name + Name string `json:"name"` + // Description define a description + Description string `json:"description"` + // OrganizationID define the namespace owner + OrganizationID string `json:"organization_id"` + // IsPublic define the default visibility policy + IsPublic bool `json:"is_public"` +} + +// CreateNamespace create a new namespace +func (s *API) CreateNamespace(req *CreateNamespaceRequest, opts ...scw.RequestOption) (*Namespace, error) { + var err error + + if req.OrganizationID == "" { + defaultOrganizationID, _ := s.client.GetDefaultOrganizationID() + req.OrganizationID = defaultOrganizationID + } + + if req.Region == "" { + defaultRegion, _ := s.client.GetDefaultRegion() + req.Region = defaultRegion + } + + if fmt.Sprint(req.Region) == "" { + return nil, errors.New("field Region cannot be empty in request") + } + + scwReq := &scw.ScalewayRequest{ + Method: "POST", + Path: "/registry/v1/regions/" + fmt.Sprint(req.Region) + "/namespaces", + Headers: http.Header{}, + } + + err = scwReq.SetBody(req) + if err != nil { + return nil, err + } + + var resp Namespace + + err = s.client.Do(scwReq, &resp, opts...) + if err != nil { + return nil, err + } + return &resp, nil +} + +type UpdateNamespaceRequest struct { + Region scw.Region `json:"-"` + // NamespaceID namespace ID to update + NamespaceID string `json:"-"` + // Description define a description + Description *string `json:"description"` + // IsPublic define the default visibility policy + IsPublic *bool `json:"is_public"` +} + +// UpdateNamespace update an existing namespace +// +// Update the namespace associated with the given id. +func (s *API) UpdateNamespace(req *UpdateNamespaceRequest, opts ...scw.RequestOption) (*Namespace, error) { + var err error + + if req.Region == "" { + defaultRegion, _ := s.client.GetDefaultRegion() + req.Region = defaultRegion + } + + if fmt.Sprint(req.Region) == "" { + return nil, errors.New("field Region cannot be empty in request") + } + + if fmt.Sprint(req.NamespaceID) == "" { + return nil, errors.New("field NamespaceID cannot be empty in request") + } + + scwReq := &scw.ScalewayRequest{ + Method: "PATCH", + Path: "/registry/v1/regions/" + fmt.Sprint(req.Region) + "/namespaces/" + fmt.Sprint(req.NamespaceID) + "", + Headers: http.Header{}, + } + + err = scwReq.SetBody(req) + if err != nil { + return nil, err + } + + var resp Namespace + + err = s.client.Do(scwReq, &resp, opts...) + if err != nil { + return nil, err + } + return &resp, nil +} + +type DeleteNamespaceRequest struct { + Region scw.Region `json:"-"` + // NamespaceID the unique ID of the Namespace + NamespaceID string `json:"-"` +} + +// DeleteNamespace delete an existing namespace +// +// Delete the namespace associated with the given id. +func (s *API) DeleteNamespace(req *DeleteNamespaceRequest, opts ...scw.RequestOption) (*Namespace, error) { + var err error + + if req.Region == "" { + defaultRegion, _ := s.client.GetDefaultRegion() + req.Region = defaultRegion + } + + if fmt.Sprint(req.Region) == "" { + return nil, errors.New("field Region cannot be empty in request") + } + + if fmt.Sprint(req.NamespaceID) == "" { + return nil, errors.New("field NamespaceID cannot be empty in request") + } + + scwReq := &scw.ScalewayRequest{ + Method: "DELETE", + Path: "/registry/v1/regions/" + fmt.Sprint(req.Region) + "/namespaces/" + fmt.Sprint(req.NamespaceID) + "", + Headers: http.Header{}, + } + + var resp Namespace + + err = s.client.Do(scwReq, &resp, opts...) + if err != nil { + return nil, err + } + return &resp, nil +} + +type ListImagesRequest struct { + Region scw.Region `json:"-"` + // Page a positive integer to choose the page to display + Page *int32 `json:"-"` + // PageSize a positive integer lower or equal to 100 to select the number of items to display + PageSize *uint32 `json:"-"` + // OrderBy field by which to order the display of Images + // + // Default value: created_at_asc + OrderBy ListImagesRequestOrderBy `json:"-"` + // NamespaceID filter by the Namespace ID + NamespaceID *string `json:"-"` + // Name filter by the Image name (exact match) + Name *string `json:"-"` + // OrganizationID filter by Organization ID + OrganizationID *string `json:"-"` +} + +// ListImages list all your images +func (s *API) ListImages(req *ListImagesRequest, opts ...scw.RequestOption) (*ListImagesResponse, error) { + var err error + + if req.Region == "" { + defaultRegion, _ := s.client.GetDefaultRegion() + req.Region = defaultRegion + } + + defaultPageSize, exist := s.client.GetDefaultPageSize() + if (req.PageSize == nil || *req.PageSize == 0) && exist { + req.PageSize = &defaultPageSize + } + + query := url.Values{} + parameter.AddToQuery(query, "page", req.Page) + parameter.AddToQuery(query, "page_size", req.PageSize) + parameter.AddToQuery(query, "order_by", req.OrderBy) + parameter.AddToQuery(query, "namespace_id", req.NamespaceID) + parameter.AddToQuery(query, "name", req.Name) + parameter.AddToQuery(query, "organization_id", req.OrganizationID) + + if fmt.Sprint(req.Region) == "" { + return nil, errors.New("field Region cannot be empty in request") + } + + scwReq := &scw.ScalewayRequest{ + Method: "GET", + Path: "/registry/v1/regions/" + fmt.Sprint(req.Region) + "/images", + Query: query, + Headers: http.Header{}, + } + + var resp ListImagesResponse + + err = s.client.Do(scwReq, &resp, opts...) + if err != nil { + return nil, err + } + return &resp, nil +} + +// UnsafeGetTotalCount should not be used +// Internal usage only +func (r *ListImagesResponse) UnsafeGetTotalCount() uint32 { + return r.TotalCount +} + +// UnsafeAppend should not be used +// Internal usage only +func (r *ListImagesResponse) UnsafeAppend(res interface{}) (uint32, error) { + results, ok := res.(*ListImagesResponse) + if !ok { + return 0, errors.New("%T type cannot be appended to type %T", res, r) + } + + r.Images = append(r.Images, results.Images...) + r.TotalCount += uint32(len(results.Images)) + return uint32(len(results.Images)), nil +} + +type GetImageRequest struct { + Region scw.Region `json:"-"` + // ImageID the unique ID of the Image + ImageID string `json:"-"` +} + +// GetImage get a image +// +// Get the image associated with the given id. +func (s *API) GetImage(req *GetImageRequest, opts ...scw.RequestOption) (*Image, error) { + var err error + + if req.Region == "" { + defaultRegion, _ := s.client.GetDefaultRegion() + req.Region = defaultRegion + } + + if fmt.Sprint(req.Region) == "" { + return nil, errors.New("field Region cannot be empty in request") + } + + if fmt.Sprint(req.ImageID) == "" { + return nil, errors.New("field ImageID cannot be empty in request") + } + + scwReq := &scw.ScalewayRequest{ + Method: "GET", + Path: "/registry/v1/regions/" + fmt.Sprint(req.Region) + "/images/" + fmt.Sprint(req.ImageID) + "", + Headers: http.Header{}, + } + + var resp Image + + err = s.client.Do(scwReq, &resp, opts...) + if err != nil { + return nil, err + } + return &resp, nil +} + +type UpdateImageRequest struct { + Region scw.Region `json:"-"` + // ImageID image ID to update + ImageID string `json:"-"` + // Visibility a `public` image is pullable from internet without authentication, opposed to a `private` image. `inherit` will use the namespace `is_public` parameter + // + // Default value: visibility_unknown + Visibility ImageVisibility `json:"visibility"` +} + +// UpdateImage update an existing image +// +// Update the image associated with the given id. +func (s *API) UpdateImage(req *UpdateImageRequest, opts ...scw.RequestOption) (*Image, error) { + var err error + + if req.Region == "" { + defaultRegion, _ := s.client.GetDefaultRegion() + req.Region = defaultRegion + } + + if fmt.Sprint(req.Region) == "" { + return nil, errors.New("field Region cannot be empty in request") + } + + if fmt.Sprint(req.ImageID) == "" { + return nil, errors.New("field ImageID cannot be empty in request") + } + + scwReq := &scw.ScalewayRequest{ + Method: "PATCH", + Path: "/registry/v1/regions/" + fmt.Sprint(req.Region) + "/images/" + fmt.Sprint(req.ImageID) + "", + Headers: http.Header{}, + } + + err = scwReq.SetBody(req) + if err != nil { + return nil, err + } + + var resp Image + + err = s.client.Do(scwReq, &resp, opts...) + if err != nil { + return nil, err + } + return &resp, nil +} + +type DeleteImageRequest struct { + Region scw.Region `json:"-"` + // ImageID the unique ID of the Image + ImageID string `json:"-"` +} + +// DeleteImage delete an image +// +// Delete the image associated with the given id. +func (s *API) DeleteImage(req *DeleteImageRequest, opts ...scw.RequestOption) (*Image, error) { + var err error + + if req.Region == "" { + defaultRegion, _ := s.client.GetDefaultRegion() + req.Region = defaultRegion + } + + if fmt.Sprint(req.Region) == "" { + return nil, errors.New("field Region cannot be empty in request") + } + + if fmt.Sprint(req.ImageID) == "" { + return nil, errors.New("field ImageID cannot be empty in request") + } + + scwReq := &scw.ScalewayRequest{ + Method: "DELETE", + Path: "/registry/v1/regions/" + fmt.Sprint(req.Region) + "/images/" + fmt.Sprint(req.ImageID) + "", + Headers: http.Header{}, + } + + var resp Image + + err = s.client.Do(scwReq, &resp, opts...) + if err != nil { + return nil, err + } + return &resp, nil +} + +type ListTagsRequest struct { + Region scw.Region `json:"-"` + // ImageID the unique ID of the image + ImageID string `json:"-"` + // Page a positive integer to choose the page to display + Page *int32 `json:"-"` + // PageSize a positive integer lower or equal to 100 to select the number of items to display + PageSize *uint32 `json:"-"` + // OrderBy field by which to order the display of Images + // + // Default value: created_at_asc + OrderBy ListTagsRequestOrderBy `json:"-"` + // Name filter by the tag name (exact match) + Name *string `json:"-"` +} + +// ListTags list all your tags +func (s *API) ListTags(req *ListTagsRequest, opts ...scw.RequestOption) (*ListTagsResponse, error) { + var err error + + if req.Region == "" { + defaultRegion, _ := s.client.GetDefaultRegion() + req.Region = defaultRegion + } + + defaultPageSize, exist := s.client.GetDefaultPageSize() + if (req.PageSize == nil || *req.PageSize == 0) && exist { + req.PageSize = &defaultPageSize + } + + query := url.Values{} + parameter.AddToQuery(query, "page", req.Page) + parameter.AddToQuery(query, "page_size", req.PageSize) + parameter.AddToQuery(query, "order_by", req.OrderBy) + parameter.AddToQuery(query, "name", req.Name) + + if fmt.Sprint(req.Region) == "" { + return nil, errors.New("field Region cannot be empty in request") + } + + if fmt.Sprint(req.ImageID) == "" { + return nil, errors.New("field ImageID cannot be empty in request") + } + + scwReq := &scw.ScalewayRequest{ + Method: "GET", + Path: "/registry/v1/regions/" + fmt.Sprint(req.Region) + "/images/" + fmt.Sprint(req.ImageID) + "/tags", + Query: query, + Headers: http.Header{}, + } + + var resp ListTagsResponse + + err = s.client.Do(scwReq, &resp, opts...) + if err != nil { + return nil, err + } + return &resp, nil +} + +// UnsafeGetTotalCount should not be used +// Internal usage only +func (r *ListTagsResponse) UnsafeGetTotalCount() uint32 { + return r.TotalCount +} + +// UnsafeAppend should not be used +// Internal usage only +func (r *ListTagsResponse) UnsafeAppend(res interface{}) (uint32, error) { + results, ok := res.(*ListTagsResponse) + if !ok { + return 0, errors.New("%T type cannot be appended to type %T", res, r) + } + + r.Tags = append(r.Tags, results.Tags...) + r.TotalCount += uint32(len(results.Tags)) + return uint32(len(results.Tags)), nil +} + +type GetTagRequest struct { + Region scw.Region `json:"-"` + // TagID the unique ID of the Tag + TagID string `json:"-"` +} + +// GetTag get a tag +// +// Get the tag associated with the given id. +func (s *API) GetTag(req *GetTagRequest, opts ...scw.RequestOption) (*Tag, error) { + var err error + + if req.Region == "" { + defaultRegion, _ := s.client.GetDefaultRegion() + req.Region = defaultRegion + } + + if fmt.Sprint(req.Region) == "" { + return nil, errors.New("field Region cannot be empty in request") + } + + if fmt.Sprint(req.TagID) == "" { + return nil, errors.New("field TagID cannot be empty in request") + } + + scwReq := &scw.ScalewayRequest{ + Method: "GET", + Path: "/registry/v1/regions/" + fmt.Sprint(req.Region) + "/tags/" + fmt.Sprint(req.TagID) + "", + Headers: http.Header{}, + } + + var resp Tag + + err = s.client.Do(scwReq, &resp, opts...) + if err != nil { + return nil, err + } + return &resp, nil +} + +type DeleteTagRequest struct { + Region scw.Region `json:"-"` + // TagID the unique ID of the tag + TagID string `json:"-"` + // Force if two tags share the same digest the deletion will fail unless this parameter is set to true + Force bool `json:"-"` +} + +// DeleteTag delete a tag +// +// Delete the tag associated with the given id. +func (s *API) DeleteTag(req *DeleteTagRequest, opts ...scw.RequestOption) (*Tag, error) { + var err error + + if req.Region == "" { + defaultRegion, _ := s.client.GetDefaultRegion() + req.Region = defaultRegion + } + + query := url.Values{} + parameter.AddToQuery(query, "force", req.Force) + + if fmt.Sprint(req.Region) == "" { + return nil, errors.New("field Region cannot be empty in request") + } + + if fmt.Sprint(req.TagID) == "" { + return nil, errors.New("field TagID cannot be empty in request") + } + + scwReq := &scw.ScalewayRequest{ + Method: "DELETE", + Path: "/registry/v1/regions/" + fmt.Sprint(req.Region) + "/tags/" + fmt.Sprint(req.TagID) + "", + Query: query, + Headers: http.Header{}, + } + + var resp Tag + + err = s.client.Do(scwReq, &resp, opts...) + if err != nil { + return nil, err + } + return &resp, nil +} diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/api/registry/v1/registry_utils.go b/vendor/github.com/scaleway/scaleway-sdk-go/api/registry/v1/registry_utils.go new file mode 100644 index 0000000000..8e639753c2 --- /dev/null +++ b/vendor/github.com/scaleway/scaleway-sdk-go/api/registry/v1/registry_utils.go @@ -0,0 +1,49 @@ +package registry + +import ( + "time" + + "github.com/scaleway/scaleway-sdk-go/internal/async" + "github.com/scaleway/scaleway-sdk-go/internal/errors" + "github.com/scaleway/scaleway-sdk-go/scw" +) + +// WaitForNamespaceRequest is used by WaitForNamespace method +type WaitForNamespaceRequest struct { + NamespaceID string + Region scw.Region + Timeout time.Duration +} + +// WaitForNamespace wait for the namespace to be in a "terminal state" before returning. +// This function can be used to wait for a namespace to be ready for example. +func (s *API) WaitForNamespace(req *WaitForNamespaceRequest) (*Namespace, error) { + terminalStatus := map[NamespaceStatus]struct{}{ + NamespaceStatusReady: {}, + NamespaceStatusLocked: {}, + NamespaceStatusError: {}, + NamespaceStatusUnknown: {}, + } + + namespace, err := async.WaitSync(&async.WaitSyncConfig{ + Get: func() (interface{}, bool, error) { + ns, err := s.GetNamespace(&GetNamespaceRequest{ + Region: req.Region, + NamespaceID: req.NamespaceID, + }) + if err != nil { + return nil, false, err + } + + _, isTerminal := terminalStatus[ns.Status] + + return ns, isTerminal, err + }, + Timeout: req.Timeout, + IntervalStrategy: async.LinearIntervalStrategy(5 * time.Second), + }) + if err != nil { + return nil, errors.Wrap(err, "waiting for namespace failed") + } + return namespace.(*Namespace), nil +} diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/internal/async/wait.go b/vendor/github.com/scaleway/scaleway-sdk-go/internal/async/wait.go index 60fcb83e91..7e0d2158fa 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/internal/async/wait.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/internal/async/wait.go @@ -15,7 +15,7 @@ type IntervalStrategy func() <-chan time.Time // WaitSyncConfig defines the waiting options. type WaitSyncConfig struct { // This method will be called from another goroutine. - Get func() (value interface{}, err error, isTerminal bool) + Get func() (value interface{}, isTerminal bool, err error) IntervalStrategy IntervalStrategy Timeout time.Duration } @@ -43,6 +43,7 @@ func WaitSync(config *WaitSyncConfig) (terminalValue interface{}, err error) { if config.IntervalStrategy == nil { config.IntervalStrategy = LinearIntervalStrategy(defaultInterval) } + if config.Timeout == 0 { config.Timeout = defaultTimeout } @@ -54,7 +55,7 @@ func WaitSync(config *WaitSyncConfig) (terminalValue interface{}, err error) { go func() { for { // get the payload - value, err, stopCondition := config.Get() + value, stopCondition, err := config.Get() // send the payload if err != nil { diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/internal/auth/no_auth.go b/vendor/github.com/scaleway/scaleway-sdk-go/internal/auth/no_auth.go index f7ec2409dd..2181c57c25 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/internal/auth/no_auth.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/internal/auth/no_auth.go @@ -2,18 +2,18 @@ package auth import "net/http" -type noAuth struct { +type NoAuth struct { } // NewNoAuth return an auth with no authentication method -func NewNoAuth() *noAuth { - return &noAuth{} +func NewNoAuth() *NoAuth { + return &NoAuth{} } -func (t *noAuth) Headers() http.Header { +func (t *NoAuth) Headers() http.Header { return http.Header{} } -func (t *noAuth) AnonymizedHeaders() http.Header { +func (t *NoAuth) AnonymizedHeaders() http.Header { return http.Header{} } diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/internal/auth/token.go b/vendor/github.com/scaleway/scaleway-sdk-go/internal/auth/token.go index b879ee82c1..6a09027557 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/internal/auth/token.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/internal/auth/token.go @@ -10,7 +10,7 @@ type Token struct { } // XAuthTokenHeader is Scaleway standard auth header -const XAuthTokenHeader = "X-Auth-Token" +const XAuthTokenHeader = "X-Auth-Token" // #nosec G101 // NewToken create a token authentication from an // access key and a secret key diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/internal/parameter/query.go b/vendor/github.com/scaleway/scaleway-sdk-go/internal/parameter/query.go index d72854d25c..d140bd45e3 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/internal/parameter/query.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/internal/parameter/query.go @@ -27,5 +27,4 @@ func AddToQuery(query url.Values, key string, value interface{}) { default: query.Add(key, fmt.Sprint(elemValue.Interface())) } - } diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/logger/default_logger.go b/vendor/github.com/scaleway/scaleway-sdk-go/logger/default_logger.go index 6636af29d8..04316d8e5c 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/logger/default_logger.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/logger/default_logger.go @@ -94,9 +94,18 @@ func newLogger(w io.Writer, level LogLevel) *loggerT { // Info logs will be written to infoW and debugW. // Debug logs will be written to debugW. var m [4]*log.Logger - m[LogLevelError] = log.New(io.MultiWriter(debugW, infoW, warningW, errorW), severityName[LogLevelError]+": ", log.LstdFlags) - m[LogLevelWarning] = log.New(io.MultiWriter(debugW, infoW, warningW), severityName[LogLevelWarning]+": ", log.LstdFlags) - m[LogLevelInfo] = log.New(io.MultiWriter(debugW, infoW), severityName[LogLevelInfo]+": ", log.LstdFlags) - m[LogLevelDebug] = log.New(debugW, severityName[LogLevelDebug]+": ", log.LstdFlags) + + m[LogLevelError] = log.New(io.MultiWriter(debugW, infoW, warningW, errorW), + severityName[LogLevelError]+": ", log.LstdFlags) + + m[LogLevelWarning] = log.New(io.MultiWriter(debugW, infoW, warningW), + severityName[LogLevelWarning]+": ", log.LstdFlags) + + m[LogLevelInfo] = log.New(io.MultiWriter(debugW, infoW), + severityName[LogLevelInfo]+": ", log.LstdFlags) + + m[LogLevelDebug] = log.New(debugW, + severityName[LogLevelDebug]+": ", log.LstdFlags) + return &loggerT{m: m, v: level} } diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/scw/client.go b/vendor/github.com/scaleway/scaleway-sdk-go/scw/client.go index b62123a4c9..0636dc0b52 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/scw/client.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/scw/client.go @@ -151,7 +151,6 @@ var requestNumber uint32 // do performs a single HTTP request based on the ScalewayRequest object. func (c *Client) do(req *ScalewayRequest, res interface{}) (sdkErr error) { - currentRequestNumber := atomic.AddUint32(&requestNumber, 1) if req == nil { @@ -178,7 +177,6 @@ func (c *Client) do(req *ScalewayRequest, res interface{}) (sdkErr error) { } if logger.ShouldLog(logger.LogLevelDebug) { - // Keep original headers (before anonymization) originalHeaders := httpRequest.Header @@ -262,7 +260,6 @@ func (c *Client) do(req *ScalewayRequest, res interface{}) (sdkErr error) { } legacyLister.UnsafeSetTotalCount(xTotalCount) } - } return nil @@ -281,10 +278,8 @@ const maxPageCount uint32 = math.MaxUint32 // doListAll collects all pages of a List request and aggregate all results on a single response. func (c *Client) doListAll(req *ScalewayRequest, res interface{}) (err error) { - // check for lister interface if response, isLister := res.(lister); isLister { - pageCount := maxPageCount for page := uint32(1); page <= pageCount; page++ { // set current page diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/scw/config.go b/vendor/github.com/scaleway/scaleway-sdk-go/scw/config.go index e18dd34b72..f9f6e88ea3 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/scw/config.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/scw/config.go @@ -173,7 +173,6 @@ func LoadConfig() (*Config, error) { // LoadConfigFromPath read the config from the given path. func LoadConfigFromPath(path string) (*Config, error) { - file, err := ioutil.ReadFile(path) if err != nil { if pathError, isPathError := err.(*os.PathError); isPathError && pathError.Err == syscall.ENOENT { @@ -224,7 +223,6 @@ func (c *Config) GetActiveProfile() (*Profile, error) { default: return &c.Profile, nil } - } // SaveTo will save the config to the default config path. This @@ -273,7 +271,6 @@ func (c *Config) SaveTo(path string) error { } return nil - } // MergeProfiles merges profiles in a new one. The last profile has priority. diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/scw/config_legacy.go b/vendor/github.com/scaleway/scaleway-sdk-go/scw/config_legacy.go index e20bd5430c..e914fac264 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/scw/config_legacy.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/scw/config_legacy.go @@ -36,7 +36,7 @@ func (v1 *configV1) toV2() *Config { return &Config{ Profile: Profile{ DefaultOrganizationID: &v1.Organization, - SecretKey: &v1.Token, + SecretKey: &v1.Token, // ignore v1 version }, } diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/scw/custom_types.go b/vendor/github.com/scaleway/scaleway-sdk-go/scw/custom_types.go index f2161f4b92..75da2b1591 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/scw/custom_types.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/scw/custom_types.go @@ -10,6 +10,7 @@ import ( "strings" "time" + "github.com/scaleway/scaleway-sdk-go/internal/errors" "github.com/scaleway/scaleway-sdk-go/logger" ) @@ -25,8 +26,8 @@ type ServiceInfo struct { // Version is the version of the API Version string `json:"version"` - // DocumentationUrl is the a web url where the documentation of the API can be found - DocumentationUrl *string `json:"documentation_url"` + // DocumentationURL is the a web url where the documentation of the API can be found + DocumentationURL *string `json:"documentation_url"` } // File is the structure used to receive / send a file from / to the API @@ -92,32 +93,20 @@ func NewMoneyFromFloat(value float64, currencyCode string, precision int) *Money } strValue := strconv.FormatFloat(value, 'f', precision, 64) - parts := strings.Split(strValue, ".") - - money := &Money{ - CurrencyCode: currencyCode, - Units: int64(value), - Nanos: 0, + units, nanos, err := splitFloatString(strValue) + if err != nil { + panic(err) } - // Handle nanos. - if len(parts) == 2 { - // Add leading zeros. - strNanos := parts[1] + "000000000"[len(parts[1]):] - - n, err := strconv.ParseInt(strNanos, 10, 32) - if err != nil { - panic(fmt.Errorf("invalid nanos %s", strNanos)) - } - - money.Nanos = int32(n) + return &Money{ + CurrencyCode: currencyCode, + Units: units, + Nanos: nanos, } - - return money } // String returns the string representation of Money. -func (m *Money) String() string { +func (m Money) String() string { currencySignsByCodes := map[string]string{ "EUR": "€", "USD": "$", @@ -136,11 +125,11 @@ func (m *Money) String() string { } // ToFloat converts a Money object to a float. -func (m *Money) ToFloat() float64 { - return float64(m.Units) + float64(m.Nanos)/1000000000 +func (m Money) ToFloat() float64 { + return float64(m.Units) + float64(m.Nanos)/1e9 } -// Money represents a size in bytes. +// Size represents a size in bytes. type Size uint64 const ( @@ -257,3 +246,94 @@ func (n *IPNet) UnmarshalJSON(b []byte) error { return nil } + +// Duration represents a signed, fixed-length span of time represented as a +// count of seconds and fractions of seconds at nanosecond resolution. It is +// independent of any calendar and concepts like "day" or "month". It is related +// to Timestamp in that the difference between two Timestamp values is a Duration +// and it can be added or subtracted from a Timestamp. +// Range is approximately +-10,000 years. +type Duration struct { + Seconds int64 + Nanos int32 +} + +func (d *Duration) ToTimeDuration() *time.Duration { + if d == nil { + return nil + } + timeDuration := time.Duration(d.Nanos) + time.Duration(d.Seconds/1e9) + return &timeDuration +} + +func (d Duration) MarshalJSON() ([]byte, error) { + nanos := d.Nanos + if nanos < 0 { + nanos = -nanos + } + + return []byte(`"` + fmt.Sprintf("%d.%09d", d.Seconds, nanos) + `s"`), nil +} + +func (d *Duration) UnmarshalJSON(b []byte) error { + if string(b) == "null" { + return nil + } + var str string + + err := json.Unmarshal(b, &str) + if err != nil { + return err + } + if str == "" { + *d = Duration{} + return nil + } + + seconds, nanos, err := splitFloatString(strings.TrimRight(str, "s")) + if err != nil { + return err + } + + *d = Duration{ + Seconds: seconds, + Nanos: nanos, + } + + return nil +} + +// splitFloatString splits a float represented in a string, and returns its units (left-coma part) and nanos (right-coma part). +// E.g.: +// "3" ==> units = 3 | nanos = 0 +// "3.14" ==> units = 3 | nanos = 14*1e7 +// "-3.14" ==> units = -3 | nanos = -14*1e7 +func splitFloatString(input string) (units int64, nanos int32, err error) { + parts := strings.SplitN(input, ".", 2) + + // parse units as int64 + units, err = strconv.ParseInt(parts[0], 10, 64) + if err != nil { + return 0, 0, errors.Wrap(err, "invalid units") + } + + // handle nanos + if len(parts) == 2 { + // add leading zeros + strNanos := parts[1] + "000000000"[len(parts[1]):] + + // parse nanos as int32 + n, err := strconv.ParseUint(strNanos, 10, 32) + if err != nil { + return 0, 0, errors.Wrap(err, "invalid nanos") + } + + nanos = int32(n) + } + + if units < 0 { + nanos = -nanos + } + + return units, nanos, nil +} diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/scw/env.go b/vendor/github.com/scaleway/scaleway-sdk-go/scw/env.go index 5836012978..d73bdd52d7 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/scw/env.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/scw/env.go @@ -10,15 +10,16 @@ import ( // Environment variables const ( // Up-to-date - scwConfigPathEnv = "SCW_CONFIG_PATH" - scwAccessKeyEnv = "SCW_ACCESS_KEY" - scwSecretKeyEnv = "SCW_SECRET_KEY" - scwActiveProfileEnv = "SCW_PROFILE" - scwAPIURLEnv = "SCW_API_URL" - scwInsecureEnv = "SCW_INSECURE" + scwCacheDirEnv = "SCW_CACHE_DIR" + scwConfigPathEnv = "SCW_CONFIG_PATH" + scwAccessKeyEnv = "SCW_ACCESS_KEY" + scwSecretKeyEnv = "SCW_SECRET_KEY" // #nosec G101 + scwActiveProfileEnv = "SCW_PROFILE" + scwAPIURLEnv = "SCW_API_URL" + scwInsecureEnv = "SCW_INSECURE" scwDefaultOrganizationIDEnv = "SCW_DEFAULT_ORGANIZATION_ID" - scwDefaultRegionEnv = "SCW_DEFAULT_REGION" - scwDefaultZoneEnv = "SCW_DEFAULT_ZONE" + scwDefaultRegionEnv = "SCW_DEFAULT_REGION" + scwDefaultZoneEnv = "SCW_DEFAULT_ZONE" // All deprecated (cli&terraform) terraformAccessKeyEnv = "SCALEWAY_ACCESS_KEY" // used both as access key and secret key diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/scw/locality.go b/vendor/github.com/scaleway/scaleway-sdk-go/scw/locality.go index e320cab426..69278d28de 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/scw/locality.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/scw/locality.go @@ -131,7 +131,6 @@ func ParseZone(zone string) (Zone, error) { // UnmarshalJSON implements the Unmarshaler interface for a Zone. // this to call ParseZone on the string input and return the correct Zone object. func (zone *Zone) UnmarshalJSON(input []byte) error { - // parse input value as string var stringValue string err := json.Unmarshal(input, &stringValue) diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/scw/path.go b/vendor/github.com/scaleway/scaleway-sdk-go/scw/path.go index f7b0b48ced..f65c5a63fb 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/scw/path.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/scw/path.go @@ -7,9 +7,12 @@ import ( ) const ( + // XDG wiki: https://wiki.archlinux.org/index.php/XDG_Base_Directory + xdgConfigDirEnv = "XDG_CONFIG_HOME" + xdgCacheDirEnv = "XDG_CACHE_HOME" + unixHomeDirEnv = "HOME" windowsHomeDirEnv = "USERPROFILE" - xdgConfigDirEnv = "XDG_CONFIG_HOME" defaultConfigFileName = "config.yaml" ) @@ -19,8 +22,33 @@ var ( ErrNoHomeDir = errors.New("user home directory not found") ) +// GetCacheDirectory returns the default cache directory. +// Cache directory is based on the following priority order: +// - $SCW_CACHE_DIR +// - $XDG_CACHE_HOME/scw +// - $HOME/.cache/scw +// - $USERPROFILE/.cache/scw +func GetCacheDirectory() string { + cacheDir := "" + switch { + case os.Getenv(scwCacheDirEnv) != "": + cacheDir = os.Getenv(scwCacheDirEnv) + case os.Getenv(xdgCacheDirEnv) != "": + cacheDir = filepath.Join(os.Getenv(xdgCacheDirEnv), "scw") + case os.Getenv(unixHomeDirEnv) != "": + cacheDir = filepath.Join(os.Getenv(unixHomeDirEnv), ".cache", "scw") + case os.Getenv(windowsHomeDirEnv) != "": + cacheDir = filepath.Join(os.Getenv(windowsHomeDirEnv), ".cache", "scw") + default: + // TODO: fallback on local folder? + } + + // Clean the cache directory path when exiting the function + return filepath.Clean(cacheDir) +} + // GetConfigPath returns the default path. -// Default path is base on the following priority order: +// Default path is based on the following priority order: // - $SCW_CONFIG_PATH // - $XDG_CONFIG_HOME/scw/config.yaml // - $HOME/.config/scw/config.yaml @@ -33,7 +61,7 @@ func GetConfigPath() string { return filepath.Clean(configPath) } -// getConfigV2FilePath returns the path to the Scaleway CLI config file +// getConfigV2FilePath returns the path to the v2 config file func getConfigV2FilePath() (string, bool) { configDir, err := getScwConfigDir() if err != nil { @@ -42,7 +70,7 @@ func getConfigV2FilePath() (string, bool) { return filepath.Clean(filepath.Join(configDir, defaultConfigFileName)), true } -// getConfigV1FilePath returns the path to the Scaleway CLI config file +// getConfigV1FilePath returns the path to the v1 config file func getConfigV1FilePath() (string, bool) { path, err := getHomeDir() if err != nil { diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/scw/request.go b/vendor/github.com/scaleway/scaleway-sdk-go/scw/request.go index f3b14d0394..19f0dd4d58 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/scw/request.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/scw/request.go @@ -91,3 +91,14 @@ func (req *ScalewayRequest) SetBody(body interface{}) error { return nil } + +func (req *ScalewayRequest) apply(opts []RequestOption) { + for _, opt := range opts { + opt(req) + } +} + +func (req *ScalewayRequest) validate() error { + // nothing so far + return nil +} diff --git a/vendor/github.com/scaleway/scaleway-sdk-go/scw/request_option.go b/vendor/github.com/scaleway/scaleway-sdk-go/scw/request_option.go index 5f5e05afa0..a5ff376632 100644 --- a/vendor/github.com/scaleway/scaleway-sdk-go/scw/request_option.go +++ b/vendor/github.com/scaleway/scaleway-sdk-go/scw/request_option.go @@ -30,14 +30,3 @@ func WithAuthRequest(accessKey, secretKey string) RequestOption { s.auth = auth.NewToken(accessKey, secretKey) } } - -func (s *ScalewayRequest) apply(opts []RequestOption) { - for _, opt := range opts { - opt(s) - } -} - -func (s *ScalewayRequest) validate() error { - // nothing so far - return nil -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 201caf5e55..c3d745b09c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -208,7 +208,7 @@ github.com/posener/complete github.com/posener/complete/cmd github.com/posener/complete/cmd/install github.com/posener/complete/match -# github.com/scaleway/scaleway-sdk-go v1.0.0-beta.5.0.20200114152133-51f964aadcd2 +# github.com/scaleway/scaleway-sdk-go v1.0.0-beta.5.0.20200130170711-05d27d10a3b8 github.com/scaleway/scaleway-sdk-go/api/account/v2alpha1 github.com/scaleway/scaleway-sdk-go/api/baremetal/v1alpha1 github.com/scaleway/scaleway-sdk-go/api/instance/v1 @@ -216,6 +216,7 @@ github.com/scaleway/scaleway-sdk-go/api/k8s/v1beta4 github.com/scaleway/scaleway-sdk-go/api/lb/v1 github.com/scaleway/scaleway-sdk-go/api/marketplace/v1 github.com/scaleway/scaleway-sdk-go/api/rdb/v1 +github.com/scaleway/scaleway-sdk-go/api/registry/v1 github.com/scaleway/scaleway-sdk-go/internal/async github.com/scaleway/scaleway-sdk-go/internal/auth github.com/scaleway/scaleway-sdk-go/internal/errors diff --git a/website/docs/r/registry_namespace_beta.markdown b/website/docs/r/registry_namespace_beta.markdown new file mode 100644 index 0000000000..31f5bd194c --- /dev/null +++ b/website/docs/r/registry_namespace_beta.markdown @@ -0,0 +1,53 @@ +--- +layout: "scaleway" +page_title: "Scaleway: scaleway_registry_namespace_beta" +description: |- + Manages Scaleway Container Registries. +--- + +# scaleway_registry_namespace_beta + +Creates and manages Scaleway Container Registry. For more information see [the documentation](https://developers.scaleway.com/en/products/registry/api/). + +## Examples + +### Basic + +```hcl +resource "scaleway_registry_namespace_beta" "main" { + name = "main_cr" + description = "Main container registry" + is_public = false +} +``` + +## Arguments Reference + +The following arguments are supported: + +- `name` - (Required) The unique name of the container registry namespace. + +~> **Important** Updates to `name` will recreate the namespace. + +- `description` (Optional) The description of the container registry namespace. + +- `is_public` (Defaults to `false`) Whether or not the registry images stored in the namespace should be downloadable publicly (docker pull). + +- `region` - (Defaults to [provider](../index.html#region) `region`). The [region](../guides/regions_and_zones.html#regions) in which the container registry namespace should be created. + +- `organization_id` - (Defaults to [provider](../index.html#organization_id) `organization_id`) The ID of the organization the registry is associated with. + +## Attibutes Reference + +In addition to all arguments above, the following attibutes are exported: + +- `id` - The ID of the namespace +- `endpoint` - Endpoint reachable by docker. + +## Import + +Container Registry Namespace can be imported using the `{region}/{id}`, eg. + +```bash +$ terraform import scaleway_container_registy.cr01 fr-par/11111111-1111-1111-1111-111111111111 +``` \ No newline at end of file diff --git a/website/scaleway.erb b/website/scaleway.erb index f15634fe51..407951bcbe 100644 --- a/website/scaleway.erb +++ b/website/scaleway.erb @@ -109,6 +109,15 @@ +