my-cvmvpc-xxxxxxxxsubnet-xxxxyyyyresource "tencentcloud_instance" "cvm1" {instance_name = "my-cvm"availability_zone = "ap-guangzhou-4"instance_type = "SA2.MEDIUM2"instance_charge_type = "POSTPAID_BY_HOUR"image_id = "img-9qrfy1xt"allocate_public_ip = trueinternet_max_bandwidth_out = 10}
terraform apply command for the first time, the declared resource will initiate the creation process. After the creation, if you modify the configuration in the code and run terraform apply again, the update process will be initiated. Running the terraform destroy command will initiate the termination process.Provider/ResourceMap field in tencentcloud/provider.go, add the tencentcloud_instance resource structure, and define the parameter schema based on HCL. Below is the sample code:package tencentcloudimport ("github.com/hashicorp/terraform-plugin-sdk/helper/schema""github.com/hashicorp/terraform-plugin-sdk/terraform")func Provider() *schema.Provider {return &schema.Provider{ResourcesMap: map[string]*schema.Resource{"tencentcloud_xxx": { /* Other declared resources */ },"tencentcloud_yyy": { /* Other declared resources */ },"tencentcloud_instance": {Schema: map[string]*schema.Schema{"instance_name": {Optional: true, // Optional fieldType: schema.TypeString, // Field typeDescription: "Instance Name.",},"availability_zone": {Required: true, // Required fieldType: schema.TypeString,ForceNew: true, // If this field is modified and the modification is submitted, the resource will be terminated and recreated, as the server instance cannot switch the AZ.Description: "Instance available zone.",},"instance_type": {Optional: true,Type: schema.TypeString,Description: "Instance Type.",},"instance_charge_type": {Optional: true,Type: schema.TypeString,Description: "Instance charge type.",},"image_id": {Required: true,Type: schema.TypeString,Description: "Instance OS image Id.",},"allocate_public_ip": {Optional: true,Type: schema.TypeBool, // Boolean typeDescription: "Specify whether to allocate public IP.",},"internet_max_bandwidth_out": {Optional: true,Type: schema.TypeInt, // Integer typeDescription: "Specify maximum bandwith.",},},},},}}
apply, plan, or destroy in Terraform. The SDK for Terraform (v1) defines four CRUD methods:Create, which is called if terraform apply is run for creation.Read, which is called if terraform plan / import is run for remote state sync.Update, which is called if terraform apply is run for update.Delete, which is called if terraform destroy is run.schema.Resource structure. Below is the sample code:package tencentcloudimport ("github.com/hashicorp/terraform-plugin-sdk/helper/schema""github.com/hashicorp/terraform-plugin-sdk/terraform")func Provider() *schema.Provider {return &schema.Provider{ResourcesMap: map[string]*schema.Resource{"tencentcloud_xxx": { /* Other declared resources */ },"tencentcloud_yyy": { /* Other declared resources */ },"tencentcloud_instance": {Create: resourceTencentCloudInstanceCreate,Read: resourceTencentCloudInstanceRead,Update: resourceTencentCloudInstanceUpdate,Delete: resourceTencentCloudInstanceDelete,Schema: map[string]*schema.Schema{// The declaration written above (omitted)},},},}}func resourceTencentCloudInstanceCreate (d *schema.ResouceData, m interface{}) error {instanceName := d.Get("instance_name").(string)instanceType := d.Get("instance_type").(string)// ...// Run `terraform apply` for resource creationinstanceId := createInstance(¶m{Name: &instanceName,Type: &instanceType,// ...})// Set a unique ID for the created resourced.SetId(instanceId)// Sync the remote state again after resource creation for consistency checkreturn resourceTencentCloudInstanceRead(d, m)}func resourceTencentCloudInstanceRead (d *schema.ResouceData, m interface{}) error {// Run `terraform plan` after resource creation/updateinstanceId := d.Id() // The ID set in `Create`instanceInfo := getInstance(instanceId)d.Set("instance_name", instanceInfo.Name)d.Set("instance_type", instanceInfo.Type)return nil}func resourceTencentCloudInstanceUpdate (d *schema.ResouceData, m interface{}) error {// Run `terraform apply` to update existing resourcesupdateParam := ¶m{}// Check whether fields are updated, and if not, update them in combinationsif d.HasChange("instance_name") {name := d.Get("instance_name").(string)updateParam.Name = &name}if d.HasChange("instance_type") {insType := d.Get("instance_type").(string)updateParam.Type = &insType}// ...updateInstance(d.Id(), updateParam)// Sync the remote state again after resource creation for consistency checkreturn resourceTencentCloudInstanceRead(d, m)}func resourceTencentCloudInstanceDelete (d *schema.ResouceData, m interface{}) error {// Run `terraform destroy`destroyInstance(d.Id())return nil}
d.Get parameter. d.Set can write back (sync) these values. In addition, after each resource is created, you need to call d.SetId to set the unique resource index by which the specific resource instance can be located.plan apply destroy. Then, you can initiate TencentCloud API calls to manipulate resources.
CVM has the following CRUD APIs:package mainimport (cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312")func resourceTencentCloudInstanceCreate(d *schema.ResourceData, meta interface{}) error {// Read the values of the fields from HCLinstanceName := d.Get("instance_name").(string)instanceType := d.Get("instance_type").(string)imageId := d.Get("image_id").(string)instanceChargeType := d.Get("instance_charge_type").(string)zone := d.Get("availability_zone").(string)allocatePublicIp := d.Get("allocate_public_ip").(bool)internetBandWith := int64(d.Get("internet_max_bandwidth_out").(int))client, _ := cvm.NewClient(credential, "ap-guangzhou")request := cvm.NewRunInstancesRequest()// Create the parameters required by CVM in combinationsrequest.InstanceName = &instanceNamerequest.InstanceType = &instanceTyperequest.ImageId = &imageIdrequest.InstanceChargeType = &instanceChargeTyperequest.Placement = &cvm.Placement {Zone: &zone,}request.InternetAccessible = &cvm.InternetAccessible {InternetMaxBandwidthOut: &internetBandWith,PublicIpAssigned: &allocatePublicIp,}// Initiate the callid, err := client.RunInstances(request)if err != nil{return err}// Set the ID returned by the creation as the resource IDd.SetId(id)// Write back the statereturn resourceTencentCloudInstanceRead(d, meta)}
Create, implement Read, Update, and Delete:package mainimport (cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312")func resourceTencentCloudInstanceRead(d *schema.ResourceData, meta interface{}) error {// The ID set in `Create` or obtained during importid := d.Id()client, _ := cvm.NewClient(credential, "ap-guangzhou")request, _ := cvm.NewDescribeInstancesRequest()request.InstanceIds = []*string{&id}response, err := client.DescribeInstances(request)if err != nil{return err}if len(response.Response.InstanceSet) == 0 {return fmt.Errorf("instance %s not exists.", id)}instance := response.Response.InstanceSet[0]d.Set("instance_name", instance.InstanceName)d.Set("instance_type", instance.InstanceType)// `d.Set` writes back fields such as `image_id`, `instance_charge_type`, and `availability_zone` (omitted).return nil}func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}) error {id := d.Id()client, _ := cvm.NewClient(credential, "ap-guangzhou")request, _ := cvm.NewModifyInstancesAttributeRequest()request.InstanceIds = []*string{&id}// Check whether the fields are changed and add the parametersif d.HasChange("instance_name") {name := d.Get("instance_name").(string)request.InstanceName = &name}// Process other `HasChange` fields (omitted)_, err := client.ModifyInstanceAttribute(request)if err != nil{return err}return resourceTencentCloudInstanceRead(d, meta)}func resourceTencentCloudInstanceDelete(d *schema.ResourceData, meta interface{}) error {id := d.Id()client, _ := cvm.NewClient(credential, "ap-guangzhou")request, _ := cvm.NewTerminateInstancesRequest()request.InstanceIds = []*string{&id}_, err := client.TerminateInstances(request)if err != nil{return err}return nil}
terraform import <type>.<index> <id>, such as:terraform import tencentcloud_instance.cvm1 ins-abcd1234
ins-abcd1234 input for resource import. As indicated in the implemented Read method, when the ID is specified, you can use the ID to query the detailed configuration of a remote resource and automatically sync the configuration locally. Therefore, you only need to declare Importer in schema.Resource to indicate that the resource can be imported. Further sync will be taken over by Read:package tencentcloudimport ("github.com/hashicorp/terraform-plugin-sdk/helper/schema""github.com/hashicorp/terraform-plugin-sdk/terraform")func Provider() *schema.Provider {return &schema.Provider{ResourcesMap: map[string]*schema.Resource{"tencentcloud_xxx": { /* Other declared resources */ },"tencentcloud_yyy": { /* Other declared resources */ },"tencentcloud_instance": {Create: resourceTencentCloudInstanceCreate,Read: resourceTencentCloudInstanceRead,Update: resourceTencentCloudInstanceUpdate,Delete: resourceTencentCloudInstanceDelete,Schema: map[string]*schema.Schema{// The declaration written above (omitted)},// In most cases, you only need to add `schema.ImportStatePassthrough`.Importer: &schema.ResourceImporter{State: schema.ImportStatePassthrough,},},},}}
TencentOS Server 3.2 (Final), but the parameter passed in to the API is its ID img-9qrfy1xt. To get the ID based on the image name, you can use the data source to query and reference the image ID:data "tencentcloud_images" "fav_os" {filters = {image_name: "TencentOS Server 3.2",image_type: "PUBLIC_IMAGE"}}resource "tencentcloud_instance" "cvm1" {image_id = data.tencentcloud_images.fav_os.images.0.image_id}
image_id into the reference of data.tencentcloud_images.fav_os. Then, Terraform will read the data source information first and then calculate the value. Compared to a static method, a data source can effectively organize resources with dependencies.Provider/DataSourceMap field in the source code of tencentcloud/provider.go, add the tencentcloud_images structure (the names of all data sources must end with s), and define the parameter schema based on HCL:package tencentcloudimport ("github.com/hashicorp/terraform-plugin-sdk/helper/schema""github.com/hashicorp/terraform-plugin-sdk/terraform")func Provider() *schema.Provider {return &schema.Provider{DataSourceMap: map[string]*schema.Resource{"tencentcloud_xxxs": { /* Other declared data sources */ },"tencentcloud_yyys": { /* Other declared data sources */ },"tencentcloud_images": {Schema: map[string]*schema.Schema{"filters": {Optional: true,Type: schema.TypeMap, // Specify the `Map` typeDescription: "Query filter",},// Saves the result in JSON locally// TencentCloud Provider requires that every data source should have `result_output_file`."result_output_file": {Optional: true,Type: schema.TypeString,Description: "Used for store as local file.",},"result": {Computed: true, // `Computed` indicates that the field will be updated passively.Type: schema.TypeList,Description: "",Elem: &schema.Resource{Schema: map[string]*schema.Schema{"id": {Type: schema.TypeString,Computed: true,Description: "Image Id.",},"name": {Type: schema.,Computed: true,Description: "Image name.",},},},},},},},}}
Read method:package tencentcloudimport ("encoding/json""github.com/hashicorp/terraform-plugin-sdk/helper/schema""github.com/hashicorp/terraform-plugin-sdk/terraform")const ImgNameFilterKey = "image-name"func Provider() *schema.Provider {return &schema.Provider{DataSourceMap: map[string]*schema.Resource{"tencentcloud_xxxs": { /* Other declared data sources */ },"tencentcloud_yyys": { /* Other declared data sources */ },"tencentcloud_images": {Schema: map[string]*schema.Schema{ /* Omitted */},Read: func(d *schema.ResourceData, meta interface{}) {// Declare the `Client` and `request`client, _ := cvm.NewClient(credential, "ap-guangzhou")request := cvm.NewDescribeImagesRequest()// Get `Filters` of `Map` typefilters := d.Get("filters").(map[string]interface{})// Check `filters["name"]` and add parametersif name, ok := filters["name"].(string); ok {request.Filters = append(request.Filters, &cvm.Filter{Name: &ImgNameFilterKey,Values: []*string{&name}})}// Initiate the callresponse, err := client.DescribeImages(request)if err != nil{return err}// Assemble and write the `result` fieldimageSet := response.Response.ImageSetresult := make([]map[string]interface{}, 0, len(imageSet))for i := range imageSet {item := imageSet[i]result = append(result, map[string]interface{}{"id": *item.Id,"name": *item.Name,})}d.Set("result", result)// If `result_output_file` has a definition, write the result into the specified file.if v, ok := d.GetOk("result_output_file"); ok {writeToFile(v.(string), result)}return nil}},},}}
tencentcloud_images and can use the data source to query specified OS images.Feedback