-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add ucloud_instance_state resource (#152)
* add ucloud_instance_state resource * support stop_instance_before_detaching in ucloud instance
- Loading branch information
Showing
10 changed files
with
452 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
package ucloud | ||
|
||
import ( | ||
"fmt" | ||
"github.com/hashicorp/terraform-plugin-sdk/helper/resource" | ||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||
"github.com/hashicorp/terraform-plugin-sdk/helper/validation" | ||
"github.com/ucloud/ucloud-sdk-go/services/uhost" | ||
"time" | ||
) | ||
|
||
func resourceUCloudInstanceState() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceUCloudInstanceStateCreate, | ||
Read: resourceUCloudInstanceStateRead, | ||
Update: resourceUCloudInstanceStateUpdate, | ||
Delete: resourceUCloudInstanceStateDelete, | ||
Importer: &schema.ResourceImporter{ | ||
State: schema.ImportStatePassthrough, | ||
}, | ||
Schema: map[string]*schema.Schema{ | ||
"instance_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
"state": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validation.StringInSlice([]string{ | ||
"Stopped", | ||
"Running", | ||
}, false), | ||
}, | ||
"force": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceUCloudInstanceStateCreate(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*UCloudClient) | ||
instanceId := d.Get("instance_id").(string) | ||
state := d.Get("state").(string) | ||
force := d.Get("force").(bool) | ||
|
||
err := WaitAndUpdateInstanceState(client, instanceId, state, force, d.Timeout(schema.TimeoutCreate)) | ||
if err != nil { | ||
return err | ||
} | ||
d.SetId(instanceId) | ||
return resourceUCloudInstanceStateRead(d, meta) | ||
} | ||
|
||
func resourceUCloudInstanceStateRead(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*UCloudClient) | ||
instanceId := d.Id() | ||
|
||
state, err := client.getInstanceState(instanceId) | ||
if err != nil { | ||
return err | ||
} | ||
d.Set("instance_id", instanceId) | ||
d.Set("state", state) | ||
d.Set("force", d.Get("force").(bool)) | ||
return nil | ||
} | ||
|
||
func resourceUCloudInstanceStateUpdate(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*UCloudClient) | ||
instanceId := d.Id() | ||
state := d.Get("state").(string) | ||
force := d.Get("force").(bool) | ||
|
||
err := WaitAndUpdateInstanceState(client, instanceId, state, force, d.Timeout(schema.TimeoutUpdate)) | ||
if err != nil { | ||
return err | ||
} | ||
return resourceUCloudInstanceStateRead(d, meta) | ||
} | ||
|
||
func resourceUCloudInstanceStateDelete(d *schema.ResourceData, meta interface{}) error { | ||
return nil | ||
} | ||
|
||
func waitInstanceReady(client *UCloudClient, id string, timeout time.Duration) (*uhost.UHostInstanceSet, error) { | ||
stateConf := &resource.StateChangeConf{ | ||
Pending: []string{statusPending, instanceStatusInitializing, instanceStatusStarting, instanceStatusStopping, instanceStatusRebooting}, | ||
Target: []string{instanceStatusRunning, instanceStatusStopped}, | ||
Refresh: getInstanceStateRefreshFunc(client, id), | ||
Timeout: timeout, | ||
Delay: 10 * time.Second, | ||
MinTimeout: 3 * time.Second, | ||
} | ||
|
||
outputRaw, err := stateConf.WaitForState() | ||
|
||
if output, ok := outputRaw.(*uhost.UHostInstanceSet); ok { | ||
return output, err | ||
} | ||
|
||
return nil, err | ||
} | ||
|
||
func getInstanceStateRefreshFunc(client *UCloudClient, instanceId string) resource.StateRefreshFunc { | ||
return func() (interface{}, string, error) { | ||
instance, err := client.describeInstanceById(instanceId) | ||
if err != nil { | ||
if isNotFoundError(err) { | ||
return nil, statusPending, nil | ||
} | ||
return nil, "", err | ||
} | ||
|
||
state := instance.State | ||
if state == instanceStatusResizeFail { | ||
return nil, "", fmt.Errorf("resizing instance failed") | ||
} | ||
|
||
if state == instanceStatusInstallFail { | ||
return nil, "", fmt.Errorf("install failed") | ||
} | ||
|
||
return instance, state, nil | ||
} | ||
} | ||
|
||
func updateInstanceState(client *UCloudClient, instance uhost.UHostInstanceSet, state string, force bool) error { | ||
switch instance.State { | ||
case instanceStatusStopped: | ||
if state == instanceStatusRunning { | ||
return client.startInstanceById(instance.UHostId) | ||
} | ||
case instanceStatusRunning: | ||
if state == instanceStatusStopped { | ||
if force { | ||
return client.poweroffInstanceById(instance.UHostId) | ||
} else { | ||
return client.stopInstanceById(instance.UHostId) | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func WaitAndUpdateInstanceState(client *UCloudClient, instanceId string, state string, force bool, timeout time.Duration) error { | ||
instance, instanceErr := waitInstanceReady(client, instanceId, timeout) | ||
if instanceErr != nil { | ||
return fmt.Errorf("error on waiting instance reach a ready status %v", instanceErr) | ||
} | ||
err := updateInstanceState(client, *instance, state, force) | ||
if err != nil { | ||
return err | ||
} | ||
_, instanceErr = waitInstanceReady(client, instanceId, timeout) | ||
if instanceErr != nil { | ||
return fmt.Errorf("error on waiting instance reach a ready status %v", instanceErr) | ||
} | ||
return nil | ||
} |
Oops, something went wrong.