Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 70 additions & 18 deletions tencentcloud/resource_tc_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ data "tencentcloud_cdh_instances" "list" {
}

resource "tencentcloud_key_pair" "random_key" {
key_name = "tf_example_key6"
key_ids = ["tf_example_key6"]
public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDjd8fTnp7Dcuj4mLaQxf9Zs/ORgUL9fQxRCNKkPgP1paTy1I513maMX126i36Lxxl3+FUB52oVbo/FgwlIfX8hyCnv8MCxqnuSDozf1CD0/wRYHcTWAtgHQHBPCC2nJtod6cVC3kB18KeV4U7zsxmwFeBIxojMOOmcOBuh7+trRw=="
}

Expand All @@ -101,7 +101,7 @@ resource "tencentcloud_instance" "foo" {
availability_zone = var.availability_zone
instance_name = "terraform-testing"
image_id = "img-ix05e4px"
key_name = tencentcloud_key_pair.random_key.id
key_ids = [tencentcloud_key_pair.random_key.id]
placement_group_id = tencentcloud_placement_group.foo.id
security_groups = ["sg-9c3f33xk"]
system_disk_type = "CLOUD_PREMIUM"
Expand Down Expand Up @@ -424,10 +424,21 @@ func resourceTencentCloudInstance() *schema.Resource {
},
// login
"key_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "The key pair to use for the instance, it looks like `skey-16jig7tx`. Modifying will cause the instance reset.",
Type: schema.TypeString,
Optional: true,
Computed: true,
Deprecated: "Please use `key_ids` instead.",
ConflictsWith: []string{"key_ids"},
Description: "The key pair to use for the instance, it looks like `skey-16jig7tx`. Modifying will cause the instance reset.",
},
"key_ids": {
Type: schema.TypeSet,
Optional: true,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个加一个computed为true吧,虽然read里面做了判断。
以后新增属性,尽量都要加上computeed

Computed: true,
ConflictsWith: []string{"key_name", "password"},
Description: "The key pair to use for the instance, it looks like `skey-16jig7tx`. Modifying will cause the instance reset.",
Set: schema.HashString,
Elem: &schema.Schema{Type: schema.TypeString},
},
"password": {
Type: schema.TypeString,
Expand All @@ -446,7 +457,7 @@ func resourceTencentCloudInstance() *schema.Resource {
return old == new
}
},
ConflictsWith: []string{"key_name", "password"},
ConflictsWith: []string{"key_name", "key_ids", "password"},
Description: "Whether to keep image login or not, default is `false`. When the image type is private or shared or imported, this parameter can be set `true`. Modifying will cause the instance reset.",
},
"user_data": {
Expand Down Expand Up @@ -687,7 +698,10 @@ func resourceTencentCloudInstanceCreate(d *schema.ResourceData, meta interface{}

// login
request.LoginSettings = &cvm.LoginSettings{}
if v, ok := d.GetOk("key_name"); ok {
keyIds := d.Get("key_ids").(*schema.Set).List()
if len(keyIds) > 0 {
request.LoginSettings.KeyIds = helper.InterfacesStringsPoint(keyIds)
} else if v, ok := d.GetOk("key_name"); ok {
request.LoginSettings.KeyIds = []*string{helper.String(v.(string))}
}
if v, ok := d.GetOk("password"); ok {
Expand Down Expand Up @@ -753,7 +767,6 @@ func resourceTencentCloudInstanceCreate(d *schema.ResourceData, meta interface{}
}
d.SetId(instanceId)

// wait for status
//get system disk ID and data disk ID
var systemDiskId string
var dataDiskIds []string
Expand Down Expand Up @@ -904,7 +917,7 @@ func resourceTencentCloudInstanceRead(d *schema.ResourceData, meta interface{})
return err
}

if d.Get("image_id").(string) == "" || !IsContains(cvmImages, *instance.ImageId) {
if d.Get("image_id").(string) == "" || instance.ImageId == nil || !IsContains(cvmImages, *instance.ImageId) {
_ = d.Set("image_id", instance.ImageId)
}

Expand Down Expand Up @@ -1005,7 +1018,11 @@ func resourceTencentCloudInstanceRead(d *schema.ResourceData, meta interface{})
_ = d.Set("public_ip", instance.PublicIpAddresses[0])
}
if len(instance.LoginSettings.KeyIds) > 0 {
_ = d.Set("key_name", instance.LoginSettings.KeyIds[0])
if _, ok := d.GetOk("key_name"); ok {
_ = d.Set("key_name", instance.LoginSettings.KeyIds[0])
} else {
_ = d.Set("key_ids", instance.LoginSettings.KeyIds)
}
} else {
_ = d.Set("key_name", "")
}
Expand Down Expand Up @@ -1200,7 +1217,10 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
request.LoginSettings.Password = helper.String(v.(string))
}

if v, ok := d.GetOk("key_name"); ok {
if v, ok := d.GetOk("key_ids"); ok {
updateAttr = append(updateAttr, "key_ids")
request.LoginSettings.KeyIds = helper.InterfacesStringsPoint(v.(*schema.Set).List())
} else if v, ok := d.GetOk("key_name"); ok {
updateAttr = append(updateAttr, "key_name")
request.LoginSettings.KeyIds = []*string{helper.String(v.(string))}
}
Expand Down Expand Up @@ -1237,11 +1257,12 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
}

if d.HasChange("key_name") {
old, new := d.GetChange("key_name")
oldKeyId := old.(string)
keyId := new.(string)
o, n := d.GetChange("key_name")
oldKeyId := o.(string)
keyId := n.(string)

if oldKeyId != "" {
err := cvmService.UnbindKeyPair(ctx, oldKeyId, []*string{&instanceId})
err := cvmService.UnbindKeyPair(ctx, []*string{&oldKeyId}, []*string{&instanceId})
if err != nil {
return err
}
Expand All @@ -1252,7 +1273,39 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
}

if keyId != "" {
err = cvmService.BindKeyPair(ctx, keyId, instanceId)
err = cvmService.BindKeyPair(ctx, []*string{&keyId}, instanceId)
if err != nil {
return err
}
err = waitForOperationFinished(d, meta, 2*readRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false)
if err != nil {
return err
}
}
}

// support remove old `key_name` to `key_ids`, so do not follow "else"
if d.HasChange("key_ids") {
o, n := d.GetChange("key_ids")
ov := o.(*schema.Set)

nv := n.(*schema.Set)

adds := nv.Difference(ov)
removes := ov.Difference(nv)

if removes.Len() > 0 {
err := cvmService.UnbindKeyPair(ctx, helper.InterfacesStringsPoint(removes.List()), []*string{&instanceId})
if err != nil {
return err
}
err = waitForOperationFinished(d, meta, 2*readRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false)
if err != nil {
return err
}
}
if adds.Len() > 0 {
err = cvmService.BindKeyPair(ctx, helper.InterfacesStringsPoint(adds.List()), instanceId)
if err != nil {
return err
}
Expand All @@ -1261,7 +1314,6 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
return err
}
}
d.SetPartial("key_name")
}
}

Expand Down
24 changes: 16 additions & 8 deletions tencentcloud/resource_tc_instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ func TestAccTencentCloudInstanceWithPrivateIP(t *testing.T) {
})
}

func TestAccTencentCloudInstanceWithKeyPair(t *testing.T) {
func TestAccTencentCloudInstanceWithKeyPairs(t *testing.T) {
id := "tencentcloud_instance.foo"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Expand All @@ -216,25 +216,27 @@ func TestAccTencentCloudInstanceWithKeyPair(t *testing.T) {
Steps: []resource.TestStep{
{
PreConfig: func() { testAccStepPreConfigSetTempAKSK(t, ACCOUNT_TYPE_COMMON) },
Config: testAccTencentCloudInstanceWithKeyPair("key_pair_0"),
Config: testAccTencentCloudInstanceWithKeyPair(
"[tencentcloud_key_pair.key_pair_0.id, tencentcloud_key_pair.key_pair_1.id]",
),
Check: resource.ComposeTestCheckFunc(
testAccCheckTencentCloudDataSourceID(id),
testAccCheckTencentCloudInstanceExists(id),
resource.TestCheckResourceAttr(id, "instance_status", "RUNNING"),
resource.TestCheckResourceAttrSet(id, "key_name"),
resource.TestCheckResourceAttr(id, "key_ids.#", "2"),
),
},
{
PreConfig: func() {
testAccStepPreConfigSetTempAKSK(t, ACCOUNT_TYPE_COMMON)
time.Sleep(time.Duration(time.Second * 5))
},
Config: testAccTencentCloudInstanceWithKeyPair("key_pair_1"),
Config: testAccTencentCloudInstanceWithKeyPair("[tencentcloud_key_pair.key_pair_2.id]"),
Check: resource.ComposeTestCheckFunc(
testAccCheckTencentCloudDataSourceID(id),
testAccCheckTencentCloudInstanceExists(id),
resource.TestCheckResourceAttr(id, "instance_status", "RUNNING"),
resource.TestCheckResourceAttrSet(id, "key_name"),
resource.TestCheckResourceAttr(id, "key_ids.#", "1"),
),
},
},
Expand Down Expand Up @@ -811,7 +813,8 @@ resource "tencentcloud_instance" "foo" {
}
`

func testAccTencentCloudInstanceWithKeyPair(keyName string) string {
func testAccTencentCloudInstanceWithKeyPair(keyIds string) string {

return fmt.Sprintf(
defaultInstanceVariable+`
resource "tencentcloud_key_pair" "key_pair_0" {
Expand All @@ -824,16 +827,21 @@ resource "tencentcloud_key_pair" "key_pair_1" {
public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzwYE6KI8uULEvSNA2k1tlsLtMDe+x1Saw6yL3V1mk9NFws0K2BshYqsnP/BlYiGZv/Nld5xmGoA9LupOcUpyyGGSHZdBrMx1Dz9ajewe7kGowRWwwMAHTlzh9+iqeg/v6P5vW6EwK4hpGWgv06vGs3a8CzfbHu1YRbZAO/ysp3ymdL+vGvw/vzC0T+YwPMisn9wFD5FTlJ+Em6s9PzxqR/41t4YssmCwUV78ZoYL8CyB0emuB8wALvcXbdUVxMxpBEHd5U6ZP5+HPxU2WFbWqiFCuErLIZRuxFw8L/Ot+JOyNnadN1XU4crYDX5cML1i/ExXKVIDoBaLtgAJOpyeP"
}

resource "tencentcloud_key_pair" "key_pair_2" {
key_name = "key_pair_2"
public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDJ1zyoM55pKxJptZBKceZSEypPN7BOunqBR1Qj3Tz5uImJ+dwfKzggu8PGcbHtuN8D2n1BH/GDkiGFaz/sIYUJWWZudcdut+ra32MqUvk953Sztf12rsFC1+lZ1CYEgon8Lt6ehxn+61tsS31yfUmpL1mq2vuca7J0NLdPMpxIYkGlifyAMISMmxi/m7gPYpbdZTmhQQS2aOhuLm+B4MwtTvT58jqNzIaFU0h5sqAvGQfzI5pcxwYvFTeQeXjJZfaYapDHN0MAg0b/vIWWNrDLv7dlv//OKBIaL0LIzIGQS8XXhF3HlyqfDuf3bjLBIKzYGSV/DRqlEsGBgzinJZXvJZug5oq1n2njDFsdXEvL6fYsP4WLvBLiQlceQ7oXi7m5nfrwFTaX+mpo7dUOR9AcyQ1AAgCcM67orB4E33ycaArGHtpjnCnWUjqQ+yCj4EXsD4yOL77wGsmhkbboVNnYAD9MJWsFP03hZE7p/RHY0C5NfLPT3mL45oZxBpC5mis="
}

resource "tencentcloud_instance" "foo" {
instance_name = var.instance_name
availability_zone = var.availability_cvm_zone
image_id = data.tencentcloud_images.default.images.0.image_id
instance_type = data.tencentcloud_instance_types.default.instance_types.0.instance_type
key_name = tencentcloud_key_pair.%s.id
key_ids = %s
system_disk_type = "CLOUD_PREMIUM"
}
`,
keyName,
keyIds,
)
}

Expand Down
2 changes: 1 addition & 1 deletion tencentcloud/resource_tc_key_pair.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ func resourceTencentCloudKeyPairDelete(d *schema.ResourceData, meta interface{})

if len(keyPair.AssociatedInstanceIds) > 0 {
err = resource.Retry(writeRetryTimeout, func() *resource.RetryError {
errRet := cvmService.UnbindKeyPair(ctx, keyId, keyPair.AssociatedInstanceIds)
errRet := cvmService.UnbindKeyPair(ctx, []*string{&keyId}, keyPair.AssociatedInstanceIds)
if errRet != nil {
if sdkErr, ok := errRet.(*errors.TencentCloudSDKError); ok {
if sdkErr.Code == CVM_NOT_FOUND_ERROR {
Expand Down
8 changes: 4 additions & 4 deletions tencentcloud/service_tencentcloud_cvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -694,10 +694,10 @@ func (me *CvmService) DeleteKeyPair(ctx context.Context, keyId string) error {
return nil
}

func (me *CvmService) UnbindKeyPair(ctx context.Context, keyId string, instanceIds []*string) error {
func (me *CvmService) UnbindKeyPair(ctx context.Context, keyIds []*string, instanceIds []*string) error {
logId := getLogId(ctx)
request := cvm.NewDisassociateInstancesKeyPairsRequest()
request.KeyIds = []*string{&keyId}
request.KeyIds = keyIds
request.InstanceIds = instanceIds
request.ForceStop = helper.Bool(true)

Expand All @@ -714,10 +714,10 @@ func (me *CvmService) UnbindKeyPair(ctx context.Context, keyId string, instanceI
return nil
}

func (me *CvmService) BindKeyPair(ctx context.Context, keyId, instanceId string) error {
func (me *CvmService) BindKeyPair(ctx context.Context, keyIds []*string, instanceId string) error {
logId := getLogId(ctx)
request := cvm.NewAssociateInstancesKeyPairsRequest()
request.KeyIds = []*string{&keyId}
request.KeyIds = keyIds
request.InstanceIds = []*string{&instanceId}
request.ForceStop = helper.Bool(true)

Expand Down
7 changes: 4 additions & 3 deletions website/docs/r/instance.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ data "tencentcloud_cdh_instances" "list" {
}

resource "tencentcloud_key_pair" "random_key" {
key_name = "tf_example_key6"
key_ids = ["tf_example_key6"]
public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDjd8fTnp7Dcuj4mLaQxf9Zs/ORgUL9fQxRCNKkPgP1paTy1I513maMX126i36Lxxl3+FUB52oVbo/FgwlIfX8hyCnv8MCxqnuSDozf1CD0/wRYHcTWAtgHQHBPCC2nJtod6cVC3kB18KeV4U7zsxmwFeBIxojMOOmcOBuh7+trRw=="
}

Expand All @@ -112,7 +112,7 @@ resource "tencentcloud_instance" "foo" {
availability_zone = var.availability_zone
instance_name = "terraform-testing"
image_id = "img-ix05e4px"
key_name = tencentcloud_key_pair.random_key.id
key_ids = [tencentcloud_key_pair.random_key.id]
placement_group_id = tencentcloud_placement_group.foo.id
security_groups = ["sg-9c3f33xk"]
system_disk_type = "CLOUD_PREMIUM"
Expand Down Expand Up @@ -160,7 +160,8 @@ The following arguments are supported:
* `internet_charge_type` - (Optional, String) Internet charge type of the instance, Valid values are `BANDWIDTH_PREPAID`, `TRAFFIC_POSTPAID_BY_HOUR`, `BANDWIDTH_POSTPAID_BY_HOUR` and `BANDWIDTH_PACKAGE`. This value takes NO Effect when changing and does not need to be set when `allocate_public_ip` is false.
* `internet_max_bandwidth_out` - (Optional, Int) Maximum outgoing bandwidth to the public network, measured in Mbps (Mega bits per second). This value does not need to be set when `allocate_public_ip` is false.
* `keep_image_login` - (Optional, Bool) Whether to keep image login or not, default is `false`. When the image type is private or shared or imported, this parameter can be set `true`. Modifying will cause the instance reset.
* `key_name` - (Optional, String) The key pair to use for the instance, it looks like `skey-16jig7tx`. Modifying will cause the instance reset.
* `key_ids` - (Optional, Set: [`String`]) The key pair to use for the instance, it looks like `skey-16jig7tx`. Modifying will cause the instance reset.
* `key_name` - (Optional, String, **Deprecated**) Please use `key_ids` instead. The key pair to use for the instance, it looks like `skey-16jig7tx`. Modifying will cause the instance reset.
* `password` - (Optional, String) Password for the instance. In order for the new password to take effect, the instance will be restarted after the password change. Modifying will cause the instance reset.
* `placement_group_id` - (Optional, String, ForceNew) The ID of a placement group.
* `private_ip` - (Optional, String) The private IP to be assigned to this instance, must be in the provided subnet and available.
Expand Down