Skip to content

Commit 464fb02

Browse files
pmcatomineystack72
authored andcommitted
provider/azurerm: add virtual_machine_extension resource (hashicorp#9962)
Picked up from where hashicorp#6548 left off settings and protected_settings take JSON objects as strings to make extension generic TF_ACC=1 go test ./builtin/providers/azurerm -v -run "TestAccAzureRMVirtualMachineExtension" -timeout 120m === RUN TestAccAzureRMVirtualMachineExtension_importBasic --- PASS: TestAccAzureRMVirtualMachineExtension_importBasic (697.55s) === RUN TestAccAzureRMVirtualMachineExtension_basic --- PASS: TestAccAzureRMVirtualMachineExtension_basic (824.17s) === RUN TestAccAzureRMVirtualMachineExtension_concurrent --- PASS: TestAccAzureRMVirtualMachineExtension_concurrent (929.74s) === RUN TestAccAzureRMVirtualMachineExtension_linuxDiagnostics --- PASS: TestAccAzureRMVirtualMachineExtension_linuxDiagnostics (803.19s) PASS ok github.com/hashicorp/terraform/builtin/providers/azurerm 3254.663s
1 parent 4391f70 commit 464fb02

6 files changed

Lines changed: 1004 additions & 0 deletions

File tree

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package azurerm
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform/helper/acctest"
8+
"github.com/hashicorp/terraform/helper/resource"
9+
)
10+
11+
func TestAccAzureRMVirtualMachineExtension_importBasic(t *testing.T) {
12+
resourceName := "azurerm_virtual_machine_extension.test"
13+
14+
ri := acctest.RandInt()
15+
config := fmt.Sprintf(testAccAzureRMVirtualMachineExtension_basic, ri, ri, ri, ri, ri, ri, ri, ri)
16+
17+
resource.Test(t, resource.TestCase{
18+
PreCheck: func() { testAccPreCheck(t) },
19+
Providers: testAccProviders,
20+
CheckDestroy: testCheckAzureRMVirtualMachineExtensionDestroy,
21+
Steps: []resource.TestStep{
22+
resource.TestStep{
23+
Config: config,
24+
},
25+
26+
resource.TestStep{
27+
ResourceName: resourceName,
28+
ImportState: true,
29+
ImportStateVerify: true,
30+
ImportStateVerifyIgnore: []string{"protected_settings"},
31+
},
32+
},
33+
})
34+
}

builtin/providers/azurerm/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ func Provider() terraform.ResourceProvider {
8686
"azurerm_template_deployment": resourceArmTemplateDeployment(),
8787
"azurerm_traffic_manager_endpoint": resourceArmTrafficManagerEndpoint(),
8888
"azurerm_traffic_manager_profile": resourceArmTrafficManagerProfile(),
89+
"azurerm_virtual_machine_extension": resourceArmVirtualMachineExtensions(),
8990
"azurerm_virtual_machine": resourceArmVirtualMachine(),
9091
"azurerm_virtual_machine_scale_set": resourceArmVirtualMachineScaleSet(),
9192
"azurerm_virtual_network": resourceArmVirtualNetwork(),
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
package azurerm
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"net/http"
7+
"reflect"
8+
9+
"github.com/Azure/azure-sdk-for-go/arm/compute"
10+
"github.com/hashicorp/terraform/helper/schema"
11+
)
12+
13+
func resourceArmVirtualMachineExtensions() *schema.Resource {
14+
return &schema.Resource{
15+
Create: resourceArmVirtualMachineExtensionsCreate,
16+
Read: resourceArmVirtualMachineExtensionsRead,
17+
Update: resourceArmVirtualMachineExtensionsCreate,
18+
Delete: resourceArmVirtualMachineExtensionsDelete,
19+
Importer: &schema.ResourceImporter{
20+
State: schema.ImportStatePassthrough,
21+
},
22+
23+
Schema: map[string]*schema.Schema{
24+
"name": &schema.Schema{
25+
Type: schema.TypeString,
26+
Required: true,
27+
ForceNew: true,
28+
},
29+
30+
"location": &schema.Schema{
31+
Type: schema.TypeString,
32+
Required: true,
33+
ForceNew: true,
34+
StateFunc: azureRMNormalizeLocation,
35+
},
36+
37+
"resource_group_name": &schema.Schema{
38+
Type: schema.TypeString,
39+
Required: true,
40+
ForceNew: true,
41+
},
42+
43+
"virtual_machine_name": &schema.Schema{
44+
Type: schema.TypeString,
45+
Required: true,
46+
ForceNew: true,
47+
},
48+
49+
"publisher": &schema.Schema{
50+
Type: schema.TypeString,
51+
Required: true,
52+
},
53+
54+
"type": &schema.Schema{
55+
Type: schema.TypeString,
56+
Required: true,
57+
},
58+
59+
"type_handler_version": &schema.Schema{
60+
Type: schema.TypeString,
61+
Required: true,
62+
},
63+
64+
"auto_upgrade_minor_version": {
65+
Type: schema.TypeBool,
66+
Optional: true,
67+
},
68+
69+
"settings": &schema.Schema{
70+
Type: schema.TypeString,
71+
Optional: true,
72+
ValidateFunc: validateJsonString,
73+
DiffSuppressFunc: suppressDiffVirtualMachineExtensionSettings,
74+
},
75+
76+
// due to the sensitive nature, these are not returned by the API
77+
"protected_settings": &schema.Schema{
78+
Type: schema.TypeString,
79+
Optional: true,
80+
Sensitive: true,
81+
ValidateFunc: validateJsonString,
82+
DiffSuppressFunc: suppressDiffVirtualMachineExtensionSettings,
83+
},
84+
85+
"tags": tagsSchema(),
86+
},
87+
}
88+
}
89+
90+
func resourceArmVirtualMachineExtensionsCreate(d *schema.ResourceData, meta interface{}) error {
91+
client := meta.(*ArmClient).vmExtensionClient
92+
93+
name := d.Get("name").(string)
94+
location := d.Get("location").(string)
95+
vmName := d.Get("virtual_machine_name").(string)
96+
resGroup := d.Get("resource_group_name").(string)
97+
publisher := d.Get("publisher").(string)
98+
extensionType := d.Get("type").(string)
99+
typeHandlerVersion := d.Get("type_handler_version").(string)
100+
autoUpgradeMinor := d.Get("auto_upgrade_minor_version").(bool)
101+
tags := d.Get("tags").(map[string]interface{})
102+
103+
extension := compute.VirtualMachineExtension{
104+
Location: &location,
105+
Properties: &compute.VirtualMachineExtensionProperties{
106+
Publisher: &publisher,
107+
Type: &extensionType,
108+
TypeHandlerVersion: &typeHandlerVersion,
109+
AutoUpgradeMinorVersion: &autoUpgradeMinor,
110+
},
111+
Tags: expandTags(tags),
112+
}
113+
114+
if settingsString := d.Get("settings").(string); settingsString != "" {
115+
settings, err := expandArmVirtualMachineExtensionSettings(settingsString)
116+
if err != nil {
117+
return fmt.Errorf("unable to parse settings: %s", err)
118+
}
119+
extension.Properties.Settings = &settings
120+
}
121+
122+
if protectedSettingsString := d.Get("protected_settings").(string); protectedSettingsString != "" {
123+
protectedSettings, err := expandArmVirtualMachineExtensionSettings(protectedSettingsString)
124+
if err != nil {
125+
return fmt.Errorf("unable to parse protected_settings: %s", err)
126+
}
127+
extension.Properties.ProtectedSettings = &protectedSettings
128+
}
129+
130+
_, err := client.CreateOrUpdate(resGroup, vmName, name, extension, make(chan struct{}))
131+
if err != nil {
132+
return err
133+
}
134+
135+
read, err := client.Get(resGroup, vmName, name, "")
136+
if err != nil {
137+
return err
138+
}
139+
140+
if read.ID == nil {
141+
return fmt.Errorf("Cannot read Virtual Machine Extension %s (resource group %s) ID", name, resGroup)
142+
}
143+
144+
d.SetId(*read.ID)
145+
146+
return resourceArmVirtualMachineExtensionsRead(d, meta)
147+
}
148+
149+
func resourceArmVirtualMachineExtensionsRead(d *schema.ResourceData, meta interface{}) error {
150+
client := meta.(*ArmClient).vmExtensionClient
151+
152+
id, err := parseAzureResourceID(d.Id())
153+
if err != nil {
154+
return err
155+
}
156+
resGroup := id.ResourceGroup
157+
vmName := id.Path["virtualMachines"]
158+
name := id.Path["extensions"]
159+
160+
resp, err := client.Get(resGroup, vmName, name, "")
161+
if err != nil {
162+
return fmt.Errorf("Error making Read request on Virtual Machine Extension %s: %s", name, err)
163+
}
164+
if resp.StatusCode == http.StatusNotFound {
165+
d.SetId("")
166+
return nil
167+
}
168+
169+
d.Set("name", resp.Name)
170+
d.Set("location", azureRMNormalizeLocation(*resp.Location))
171+
d.Set("virtual_machine_name", vmName)
172+
d.Set("resource_group_name", resGroup)
173+
d.Set("publisher", resp.Properties.Publisher)
174+
d.Set("type", resp.Properties.Type)
175+
d.Set("type_handler_version", resp.Properties.TypeHandlerVersion)
176+
d.Set("auto_upgrade_minor_version", resp.Properties.AutoUpgradeMinorVersion)
177+
178+
if resp.Properties.Settings != nil {
179+
settings, err := flattenArmVirtualMachineExtensionSettings(*resp.Properties.Settings)
180+
if err != nil {
181+
return fmt.Errorf("unable to parse settings from response: %s", err)
182+
}
183+
d.Set("settings", settings)
184+
}
185+
186+
flattenAndSetTags(d, resp.Tags)
187+
188+
return nil
189+
}
190+
191+
func resourceArmVirtualMachineExtensionsDelete(d *schema.ResourceData, meta interface{}) error {
192+
client := meta.(*ArmClient).vmExtensionClient
193+
194+
id, err := parseAzureResourceID(d.Id())
195+
if err != nil {
196+
return err
197+
}
198+
resGroup := id.ResourceGroup
199+
name := id.Path["extensions"]
200+
vmName := id.Path["virtualMachines"]
201+
202+
_, err = client.Delete(resGroup, vmName, name, make(chan struct{}))
203+
204+
return nil
205+
}
206+
207+
func expandArmVirtualMachineExtensionSettings(jsonString string) (map[string]interface{}, error) {
208+
var result map[string]interface{}
209+
210+
err := json.Unmarshal([]byte(jsonString), &result)
211+
212+
return result, err
213+
}
214+
215+
func flattenArmVirtualMachineExtensionSettings(settingsMap map[string]interface{}) (string, error) {
216+
result, err := json.Marshal(settingsMap)
217+
if err != nil {
218+
return "", err
219+
}
220+
221+
return string(result), nil
222+
}
223+
224+
func suppressDiffVirtualMachineExtensionSettings(k, old, new string, d *schema.ResourceData) bool {
225+
oldMap, err := expandArmVirtualMachineExtensionSettings(old)
226+
if err != nil {
227+
return false
228+
}
229+
230+
newMap, err := expandArmVirtualMachineExtensionSettings(new)
231+
if err != nil {
232+
return false
233+
}
234+
235+
return reflect.DeepEqual(oldMap, newMap)
236+
}

0 commit comments

Comments
 (0)