diff --git a/go.mod b/go.mod index 6d1a04f0ab7..887c6b82b8b 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/hashicorp/errwrap v1.0.0 github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/terraform-plugin-sdk v1.16.0 - github.com/huaweicloud/golangsdk v0.0.0-20210722084309-4039dc70b08a + github.com/huaweicloud/golangsdk v0.0.0-20210727014057-a2f63cd07e36 github.com/jen20/awspolicyequivalence v1.1.0 github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa // indirect github.com/stretchr/testify v1.4.0 diff --git a/go.sum b/go.sum index 153cc1863f5..611cc0770d4 100644 --- a/go.sum +++ b/go.sum @@ -206,8 +206,8 @@ github.com/hashicorp/terraform-svchost v0.0.0-20191011084731-65d371908596/go.mod github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= -github.com/huaweicloud/golangsdk v0.0.0-20210722084309-4039dc70b08a h1:pkd1CUV6rI7CCzlZ+pQRQa8UdSOgxAwn2GtLZFsI34c= -github.com/huaweicloud/golangsdk v0.0.0-20210722084309-4039dc70b08a/go.mod h1:fcOI5u+0f62JtJd7zkCch/Z57BNC6bhqb32TKuiF4r0= +github.com/huaweicloud/golangsdk v0.0.0-20210727014057-a2f63cd07e36 h1:2oW1oYgSD2XWc3NymcBXrKm0laRiYXw2hCyMNML9j9E= +github.com/huaweicloud/golangsdk v0.0.0-20210727014057-a2f63cd07e36/go.mod h1:fcOI5u+0f62JtJd7zkCch/Z57BNC6bhqb32TKuiF4r0= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg= github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= diff --git a/huaweicloud/resource_huaweicloud_cce_node_v3.go b/huaweicloud/resource_huaweicloud_cce_node_v3.go index 09aa37c7f40..5bcf52fa960 100644 --- a/huaweicloud/resource_huaweicloud_cce_node_v3.go +++ b/huaweicloud/resource_huaweicloud_cce_node_v3.go @@ -302,6 +302,11 @@ func ResourceCCENodeV3() *schema.Resource { Optional: true, ForceNew: true, }, + "keep_ecs": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, "private_ip": { Type: schema.TypeString, Computed: true, @@ -760,43 +765,72 @@ func resourceCCENodeV3Delete(d *schema.ResourceData, meta interface{}) error { } clusterid := d.Get("cluster_id").(string) - // for prePaid node, firstly, we should unsubscribe the ecs server, and then delete it - if d.Get("charging_mode").(string) == "prePaid" || d.Get("billing_mode").(int) == 2 { - serverID := d.Get("server_id").(string) - publicIP := d.Get("public_ip").(string) + // remove node without deleting ecs + if d.Get("keep_ecs").(bool) { + var removeOpts nodes.RemoveOpts + + var loginSpec nodes.LoginSpec + if hasFilledOpt(d, "key_pair") { + loginSpec = nodes.LoginSpec{ + SshKey: d.Get("key_pair").(string), + } + } else if hasFilledOpt(d, "password") { + loginSpec = nodes.LoginSpec{ + UserPassword: nodes.UserPassword{ + Username: "root", + Password: d.Get("password").(string), + }, + } + } + removeOpts.Spec.Login = loginSpec - resourceIDs := make([]string, 0, 2) - if serverID != "" { - resourceIDs = append(resourceIDs, serverID) + nodeItem := nodes.NodeItem{ + Uid: d.Id(), } + removeOpts.Spec.Nodes = append(removeOpts.Spec.Nodes, nodeItem) - // unsubscribe the eip if necessary - if _, ok := d.GetOk("iptype"); ok && publicIP != "" { - eipClient, err := config.NetworkingV1Client(GetRegion(d, config)) - if err != nil { - return fmtp.Errorf("Error creating networking client: %s", err) + err = nodes.Remove(nodeClient, clusterid, removeOpts).ExtractErr() + if err != nil { + return fmtp.Errorf("Error removing HuaweiCloud CCE node: %s", err) + } + } else { + // for prePaid node, firstly, we should unsubscribe the ecs server, and then delete it + if d.Get("charging_mode").(string) == "prePaid" || d.Get("billing_mode").(int) == 2 { + serverID := d.Get("server_id").(string) + publicIP := d.Get("public_ip").(string) + + resourceIDs := make([]string, 0, 2) + if serverID != "" { + resourceIDs = append(resourceIDs, serverID) } - if eipID, err := getEipIDbyAddress(eipClient, publicIP); err == nil { - resourceIDs = append(resourceIDs, eipID) - } else { - logp.Printf("[WARN] Error fetching EIP ID of CCE Node (%s): %s", d.Id(), err) + // unsubscribe the eip if necessary + if _, ok := d.GetOk("iptype"); ok && publicIP != "" { + eipClient, err := config.NetworkingV1Client(GetRegion(d, config)) + if err != nil { + return fmtp.Errorf("Error creating networking client: %s", err) + } + + if eipID, err := getEipIDbyAddress(eipClient, publicIP); err == nil { + resourceIDs = append(resourceIDs, eipID) + } else { + logp.Printf("[WARN] Error fetching EIP ID of CCE Node (%s): %s", d.Id(), err) + } } - } - if len(resourceIDs) > 0 { - if err := UnsubscribePrePaidResource(d, config, resourceIDs); err != nil { - return fmtp.Errorf("Error unsubscribing HuaweiCloud CCE node: %s", err) + if len(resourceIDs) > 0 { + if err := UnsubscribePrePaidResource(d, config, resourceIDs); err != nil { + return fmtp.Errorf("Error unsubscribing HuaweiCloud CCE node: %s", err) + } } } - } - time.Sleep(60 * time.Second) //lintignore:R018 - err = nodes.Delete(nodeClient, clusterid, d.Id()).ExtractErr() - if err != nil { - return fmtp.Errorf("Error deleting HuaweiCloud CCE node: %s", err) + time.Sleep(60 * time.Second) //lintignore:R018 + err = nodes.Delete(nodeClient, clusterid, d.Id()).ExtractErr() + if err != nil { + return fmtp.Errorf("Error deleting HuaweiCloud CCE node: %s", err) + } } - stateConf := &resource.StateChangeConf{ Pending: []string{"Deleting"}, Target: []string{"Deleted"}, diff --git a/vendor/github.com/huaweicloud/golangsdk/errors.go b/vendor/github.com/huaweicloud/golangsdk/errors.go index 1d56d247c11..7224fe40ad2 100644 --- a/vendor/github.com/huaweicloud/golangsdk/errors.go +++ b/vendor/github.com/huaweicloud/golangsdk/errors.go @@ -145,7 +145,11 @@ func (e ErrDefault429) Error() string { return e.choseErrString() } func (e ErrDefault500) Error() string { - return "Internal Server Error" + e.DefaultErrString = fmt.Sprintf( + "Internal Server Error: [%s %s], error message: %s", + e.Method, e.URL, e.Body, + ) + return e.choseErrString() } func (e ErrDefault503) Error() string { return "The service is currently unable to handle the request due to a temporary" + diff --git a/vendor/github.com/huaweicloud/golangsdk/openstack/cce/v3/nodes/requests.go b/vendor/github.com/huaweicloud/golangsdk/openstack/cce/v3/nodes/requests.go index 1dd33cf61ec..1b09a2e8ec4 100644 --- a/vendor/github.com/huaweicloud/golangsdk/openstack/cce/v3/nodes/requests.go +++ b/vendor/github.com/huaweicloud/golangsdk/openstack/cce/v3/nodes/requests.go @@ -185,6 +185,47 @@ func Delete(c *golangsdk.ServiceClient, clusterid, nodeid string) (r DeleteResul return } +type RemoveOptsBuilder interface { + ToNodeRemoveMap() (map[string]interface{}, error) +} + +type RemoveOpts struct { + // API type, fixed value RemoveNodesTask + Kind string `json:"kind,omitempty"` + // API version, fixed value v3 + Apiversion string `json:"apiVersion,omitempty"` + + Spec RemoveNodeSpec `json:"spec" required:"true"` +} + +type RemoveNodeSpec struct { + Login LoginSpec `json:"login" required:"true"` + Nodes []NodeItem `json:"nodes,omitempty"` +} + +type NodeItem struct { + Uid string `json:"uid,omitempty"` +} + +func (opts RemoveOpts) ToNodeRemoveMap() (map[string]interface{}, error) { + return golangsdk.BuildRequestBody(opts, "") +} + +func Remove(c *golangsdk.ServiceClient, clusterid string, opts RemoveOptsBuilder) (r DeleteResult) { + b, err := opts.ToNodeRemoveMap() + if err != nil { + r.Err = err + return + } + + _, r.Err = c.Put(removeNodeURL(c, clusterid), b, nil, &golangsdk.RequestOpts{ + OkCodes: []int{200}, + MoreHeaders: RequestOpts.MoreHeaders, JSONBody: nil, + }) + + return +} + // GetJobDetails retrieves a particular job based on its unique ID func GetJobDetails(c *golangsdk.ServiceClient, jobid string) (r GetResult) { _, r.Err = c.Get(getJobURL(c, jobid), &r.Body, &golangsdk.RequestOpts{ diff --git a/vendor/github.com/huaweicloud/golangsdk/openstack/cce/v3/nodes/urls.go b/vendor/github.com/huaweicloud/golangsdk/openstack/cce/v3/nodes/urls.go index 229214112ec..131282e0096 100644 --- a/vendor/github.com/huaweicloud/golangsdk/openstack/cce/v3/nodes/urls.go +++ b/vendor/github.com/huaweicloud/golangsdk/openstack/cce/v3/nodes/urls.go @@ -18,3 +18,7 @@ func resourceURL(c *golangsdk.ServiceClient, clusterid, nodeid string) string { func getJobURL(c *golangsdk.ServiceClient, jobid string) string { return c.ServiceURL("jobs", jobid) } + +func removeNodeURL(c *golangsdk.ServiceClient, clusterid string) string { + return c.ServiceURL(rootPath, clusterid, resourcePath, "operation/remove") +} diff --git a/vendor/github.com/huaweicloud/golangsdk/openstack/scm/v3/certificates/requests.go b/vendor/github.com/huaweicloud/golangsdk/openstack/scm/v3/certificates/requests.go index 0710e2948ee..19a66e97fb9 100644 --- a/vendor/github.com/huaweicloud/golangsdk/openstack/scm/v3/certificates/requests.go +++ b/vendor/github.com/huaweicloud/golangsdk/openstack/scm/v3/certificates/requests.go @@ -6,6 +6,10 @@ import ( "github.com/huaweicloud/golangsdk" ) +var RequestOpts golangsdk.RequestOpts = golangsdk.RequestOpts{ + MoreHeaders: map[string]string{"Content-Type": "application/json", "X-Language": "en-us"}, +} + // ImportOptsBuilder is the interface options structs have to satisfy in order // to be used in the Import operation in this package. type ImportOptsBuilder interface { @@ -39,7 +43,8 @@ func Import(c *golangsdk.ServiceClient, opts ImportOptsBuilder) (r ImportResult) return } _, r.Err = c.Post(importURL(c), b, &r.Body, &golangsdk.RequestOpts{ - OkCodes: []int{200, 201}, + OkCodes: []int{200, 201}, + MoreHeaders: RequestOpts.MoreHeaders, }) return } @@ -70,7 +75,8 @@ func Push(c *golangsdk.ServiceClient, id string, opts PushOptsBuilder) (r PushRe } _, r.Err = c.Post(pushURL(c, id), b, nil, &golangsdk.RequestOpts{ - OkCodes: []int{204}, + OkCodes: []int{204}, + MoreHeaders: RequestOpts.MoreHeaders, }) return } @@ -78,7 +84,10 @@ func Push(c *golangsdk.ServiceClient, id string, opts PushOptsBuilder) (r PushRe // Obtain information about the imported certificate by ID. // Contain no certificate key or private key. func Get(c *golangsdk.ServiceClient, id string) (r GetResult) { - _, r.Err = c.Get(resourceURL(c, id), &r.Body, nil) + _, r.Err = c.Get(resourceURL(c, id), &r.Body, &golangsdk.RequestOpts{ + OkCodes: []int{200}, + MoreHeaders: RequestOpts.MoreHeaders, + }) return } @@ -86,7 +95,8 @@ func Get(c *golangsdk.ServiceClient, id string) (r GetResult) { func Export(c *golangsdk.ServiceClient, id string) (r ExportResult) { body := map[string]interface{}{} _, r.Err = c.Post(exportURL(c, id), body, &r.Body, &golangsdk.RequestOpts{ - OkCodes: []int{200, 201}, + OkCodes: []int{200, 201}, + MoreHeaders: RequestOpts.MoreHeaders, }) return } diff --git a/vendor/modules.txt b/vendor/modules.txt index 97b83f67b0d..1e6152174a2 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -267,7 +267,7 @@ github.com/hashicorp/terraform-svchost/auth github.com/hashicorp/terraform-svchost/disco # github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d github.com/hashicorp/yamux -# github.com/huaweicloud/golangsdk v0.0.0-20210722084309-4039dc70b08a +# github.com/huaweicloud/golangsdk v0.0.0-20210727014057-a2f63cd07e36 ## explicit github.com/huaweicloud/golangsdk github.com/huaweicloud/golangsdk/internal