Skip to content

Commit 6ea0397

Browse files
committed
Made instances deployable on already existing services.
1 parent c1ac726 commit 6ea0397

4 files changed

Lines changed: 214 additions & 81 deletions

File tree

builtin/providers/azure/provider_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ import (
1111
var testAccProviders map[string]terraform.ResourceProvider
1212
var testAccProvider *schema.Provider
1313

14-
const testAccSecurityGroupName = "terraform-security-group"
14+
const (
15+
testAccSecurityGroupName = "terraform-security-group"
16+
testAccHostedServiceName = "terraform-testing-service"
17+
)
1518

1619
// testAccStorageServiceName is used as the name for the Storage Service
1720
// created in all storage-related tests.

builtin/providers/azure/resource_azure_instance.go

Lines changed: 90 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ func resourceAzureInstance() *schema.Resource {
3737
ForceNew: true,
3838
},
3939

40+
"hosted_service_name": &schema.Schema{
41+
Type: schema.TypeString,
42+
Optional: true,
43+
Computed: true,
44+
ForceNew: true,
45+
},
46+
4047
"description": &schema.Schema{
4148
Type: schema.TypeString,
4249
Optional: true,
@@ -197,36 +204,30 @@ func resourceAzureInstanceCreate(d *schema.ResourceData, meta interface{}) (err
197204
return err
198205
}
199206

200-
p := hostedservice.CreateHostedServiceParameters{
201-
ServiceName: name,
202-
Label: base64.StdEncoding.EncodeToString([]byte(name)),
203-
Description: fmt.Sprintf("Cloud Service created automatically for instance %s", name),
204-
Location: d.Get("location").(string),
205-
ReverseDNSFqdn: d.Get("reverse_dns").(string),
206-
}
207+
var hostedServiceName string
208+
// check if hosted service name parameter was given:
209+
if serviceName, ok := d.GetOk("hosted_service_name"); !ok {
210+
// if not provided; just use the name of the instance to create a new one:
211+
hostedServiceName = name
212+
d.Set("hosted_service_name", hostedServiceName)
207213

208-
log.Printf("[DEBUG] Creating Cloud Service for instance: %s", name)
209-
err = hostedServiceClient.CreateHostedService(p)
210-
if err != nil {
211-
return fmt.Errorf("Error creating Cloud Service for instance %s: %s", name, err)
212-
}
214+
p := hostedservice.CreateHostedServiceParameters{
215+
ServiceName: hostedServiceName,
216+
Label: base64.StdEncoding.EncodeToString([]byte(name)),
217+
Description: fmt.Sprintf("Cloud Service created automatically for instance %s", name),
218+
Location: d.Get("location").(string),
219+
ReverseDNSFqdn: d.Get("reverse_dns").(string),
220+
}
213221

214-
// Put in this defer here, so we are sure to cleanup already created parts
215-
// when we exit with an error
216-
defer func(mc management.Client) {
222+
log.Printf("[DEBUG] Creating Cloud Service for instance: %s", name)
223+
err = hostedServiceClient.CreateHostedService(p)
217224
if err != nil {
218-
req, err := hostedServiceClient.DeleteHostedService(name, true)
219-
if err != nil {
220-
log.Printf("[DEBUG] Error cleaning up Cloud Service of instance %s: %s", name, err)
221-
}
222-
223-
// Wait until the Cloud Service is deleted
224-
if err := mc.WaitForOperation(req, nil); err != nil {
225-
log.Printf(
226-
"[DEBUG] Error waiting for Cloud Service of instance %s to be deleted: %s", name, err)
227-
}
225+
return fmt.Errorf("Error creating Cloud Service for instance %s: %s", name, err)
228226
}
229-
}(mc)
227+
} else {
228+
// else; use the provided hosted service name:
229+
hostedServiceName = serviceName.(string)
230+
}
230231

231232
// Create a new role for the instance
232233
role := vmutils.NewVMConfiguration(name, d.Get("size").(string))
@@ -312,7 +313,7 @@ func resourceAzureInstanceCreate(d *schema.ResourceData, meta interface{}) (err
312313
}
313314

314315
log.Printf("[DEBUG] Creating the new instance...")
315-
req, err := vmClient.CreateDeployment(role, name, options)
316+
req, err := vmClient.CreateDeployment(role, hostedServiceName, options)
316317
if err != nil {
317318
return fmt.Errorf("Error creating instance %s: %s", name, err)
318319
}
@@ -333,36 +334,49 @@ func resourceAzureInstanceRead(d *schema.ResourceData, meta interface{}) error {
333334
hostedServiceClient := azureClient.hostedServiceClient
334335
vmClient := azureClient.vmClient
335336

336-
log.Printf("[DEBUG] Retrieving Cloud Service for instance: %s", d.Id())
337-
cs, err := hostedServiceClient.GetHostedService(d.Id())
337+
name := d.Get("name").(string)
338+
339+
// check if the instance belongs to an independent hosted service
340+
// or it had one created for it.
341+
var hostedServiceName string
342+
if serviceName, ok := d.GetOk("hosted_service_name"); ok {
343+
// if independent; use that hosted service name:
344+
hostedServiceName = serviceName.(string)
345+
} else {
346+
// else; suppose it's the instance's name:
347+
hostedServiceName = name
348+
}
349+
350+
log.Printf("[DEBUG] Retrieving Cloud Service for instance: %s", name)
351+
cs, err := hostedServiceClient.GetHostedService(hostedServiceName)
338352
if err != nil {
339-
return fmt.Errorf("Error retrieving Cloud Service of instance %s: %s", d.Id(), err)
353+
return fmt.Errorf("Error retrieving Cloud Service of instance %s (%q): %s", name, hostedServiceName, err)
340354
}
341355

342356
d.Set("reverse_dns", cs.ReverseDNSFqdn)
343357
d.Set("location", cs.Location)
344358

345-
log.Printf("[DEBUG] Retrieving instance: %s", d.Id())
346-
dpmt, err := vmClient.GetDeployment(d.Id(), d.Id())
359+
log.Printf("[DEBUG] Retrieving instance: %s", name)
360+
dpmt, err := vmClient.GetDeployment(hostedServiceName, name)
347361
if err != nil {
348362
if management.IsResourceNotFoundError(err) {
349363
d.SetId("")
350364
return nil
351365
}
352-
return fmt.Errorf("Error retrieving instance %s: %s", d.Id(), err)
366+
return fmt.Errorf("Error retrieving instance %s: %s", name, err)
353367
}
354368

355369
if len(dpmt.RoleList) != 1 {
356370
return fmt.Errorf(
357-
"Instance %s has an unexpected number of roles: %d", d.Id(), len(dpmt.RoleList))
371+
"Instance %s has an unexpected number of roles: %d", name, len(dpmt.RoleList))
358372
}
359373

360374
d.Set("size", dpmt.RoleList[0].RoleSize)
361375

362376
if len(dpmt.RoleInstanceList) != 1 {
363377
return fmt.Errorf(
364378
"Instance %s has an unexpected number of role instances: %d",
365-
d.Id(), len(dpmt.RoleInstanceList))
379+
name, len(dpmt.RoleInstanceList))
366380
}
367381
d.Set("ip_address", dpmt.RoleInstanceList[0].IPAddress)
368382

@@ -400,7 +414,7 @@ func resourceAzureInstanceRead(d *schema.ResourceData, meta interface{}) error {
400414
default:
401415
return fmt.Errorf(
402416
"Instance %s has an unexpected number of associated subnets %d",
403-
d.Id(), len(dpmt.RoleInstanceList))
417+
name, len(dpmt.RoleInstanceList))
404418
}
405419

406420
// Update the security group
@@ -434,10 +448,13 @@ func resourceAzureInstanceUpdate(d *schema.ResourceData, meta interface{}) error
434448
return nil
435449
}
436450

451+
name := d.Get("name").(string)
452+
hostedServiceName := d.Get("hosted_service_name").(string)
453+
437454
// Get the current role
438-
role, err := vmClient.GetRole(d.Id(), d.Id(), d.Id())
455+
role, err := vmClient.GetRole(hostedServiceName, name, name)
439456
if err != nil {
440-
return fmt.Errorf("Error retrieving role of instance %s: %s", d.Id(), err)
457+
return fmt.Errorf("Error retrieving role of instance %s: %s", name, err)
441458
}
442459

443460
// Verify if we have all required parameters
@@ -473,7 +490,7 @@ func resourceAzureInstanceUpdate(d *schema.ResourceData, meta interface{}) error
473490
)
474491
if err != nil {
475492
return fmt.Errorf(
476-
"Error adding endpoint %s for instance %s: %s", m["name"].(string), d.Id(), err)
493+
"Error adding endpoint %s for instance %s: %s", m["name"].(string), name, err)
477494
}
478495
}
479496
}
@@ -484,19 +501,19 @@ func resourceAzureInstanceUpdate(d *schema.ResourceData, meta interface{}) error
484501
err := vmutils.ConfigureWithSecurityGroup(role, sg)
485502
if err != nil {
486503
return fmt.Errorf(
487-
"Error associating security group %s with instance %s: %s", sg, d.Id(), err)
504+
"Error associating security group %s with instance %s: %s", sg, name, err)
488505
}
489506
}
490507

491508
// Update the adjusted role
492-
req, err := vmClient.UpdateRole(d.Id(), d.Id(), d.Id(), *role)
509+
req, err := vmClient.UpdateRole(hostedServiceName, name, name, *role)
493510
if err != nil {
494-
return fmt.Errorf("Error updating role of instance %s: %s", d.Id(), err)
511+
return fmt.Errorf("Error updating role of instance %s: %s", name, err)
495512
}
496513

497514
if err := mc.WaitForOperation(req, nil); err != nil {
498515
return fmt.Errorf(
499-
"Error waiting for role of instance %s to be updated: %s", d.Id(), err)
516+
"Error waiting for role of instance %s to be updated: %s", name, err)
500517
}
501518

502519
return resourceAzureInstanceRead(d, meta)
@@ -505,21 +522,40 @@ func resourceAzureInstanceUpdate(d *schema.ResourceData, meta interface{}) error
505522
func resourceAzureInstanceDelete(d *schema.ResourceData, meta interface{}) error {
506523
azureClient := meta.(*Client)
507524
mc := azureClient.mgmtClient
525+
vmClient := azureClient.vmClient
508526
hostedServiceClient := azureClient.hostedServiceClient
509527

510-
log.Printf("[DEBUG] Deleting instance: %s", d.Id())
511-
req, err := hostedServiceClient.DeleteHostedService(d.Id(), true)
512-
if err != nil {
513-
return fmt.Errorf("Error deleting instance %s: %s", d.Id(), err)
514-
}
528+
name := d.Get("name").(string)
529+
hostedServiceName := d.Get("hosted_service_name").(string)
515530

516-
// Wait until the instance is deleted
517-
if err := mc.WaitForOperation(req, nil); err != nil {
518-
return fmt.Errorf(
519-
"Error waiting for instance %s to be deleted: %s", d.Id(), err)
520-
}
531+
log.Printf("[DEBUG] Deleting instance: %s", name)
521532

522-
d.SetId("")
533+
// check if the instance had a hosted service created especially for it:
534+
if name == hostedServiceName {
535+
// if so; we must delete the associated hosted service as well:
536+
req, err := hostedServiceClient.DeleteHostedService(name, true)
537+
if err != nil {
538+
return fmt.Errorf("Error deleting instance and hosted service %s: %s", name, err)
539+
}
540+
541+
// Wait until the hosted service and the instance it contains is deleted:
542+
if err := mc.WaitForOperation(req, nil); err != nil {
543+
return fmt.Errorf(
544+
"Error waiting for instance %s to be deleted: %s", name, err)
545+
}
546+
} else {
547+
// else; just delete the instance:
548+
reqID, err := vmClient.DeleteDeployment(hostedServiceName, name)
549+
if err != nil {
550+
return fmt.Errorf("Error deleting instance %s off hosted service %s: %s", name, hostedServiceName, err)
551+
}
552+
553+
// and wait for the deletion:
554+
if err := mc.WaitForOperation(reqID, nil); err != nil {
555+
return fmt.Errorf("Error waiting for intance %s to be deleted off the hosted service %s: %s",
556+
name, hostedServiceName, err)
557+
}
558+
}
523559

524560
return nil
525561
}

0 commit comments

Comments
 (0)