Skip to content

Commit 463093e

Browse files
authored
azurerm_automation_dsc_nodeconfiguration - Split CreateUpdate into separate Create and Update functions (#31973)
1 parent 7035d18 commit 463093e

2 files changed

Lines changed: 139 additions & 27 deletions

File tree

internal/services/automation/automation_dsc_nodeconfiguration_resource.go

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ import (
2323

2424
func resourceAutomationDscNodeConfiguration() *pluginsdk.Resource {
2525
return &pluginsdk.Resource{
26-
Create: resourceAutomationDscNodeConfigurationCreateUpdate,
26+
Create: resourceAutomationDscNodeConfigurationCreate,
2727
Read: resourceAutomationDscNodeConfigurationRead,
28-
Update: resourceAutomationDscNodeConfigurationCreateUpdate,
28+
Update: resourceAutomationDscNodeConfigurationUpdate,
2929
Delete: resourceAutomationDscNodeConfigurationDelete,
3030

3131
Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error {
@@ -71,61 +71,89 @@ func resourceAutomationDscNodeConfiguration() *pluginsdk.Resource {
7171
}
7272
}
7373

74-
func resourceAutomationDscNodeConfigurationCreateUpdate(d *pluginsdk.ResourceData, meta interface{}) error {
74+
func resourceAutomationDscNodeConfigurationCreate(d *pluginsdk.ResourceData, meta interface{}) error {
7575
client := meta.(*clients.Client).Automation.DscNodeConfiguration
7676
subscriptionId := meta.(*clients.Client).Account.SubscriptionId
77-
ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d)
77+
ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d)
7878
defer cancel()
7979

8080
log.Printf("[INFO] preparing arguments for AzureRM Automation Dsc Node Configuration creation.")
8181

8282
id := dscnodeconfiguration.NewNodeConfigurationID(subscriptionId, d.Get("resource_group_name").(string), d.Get("automation_account_name").(string), d.Get("name").(string))
8383

84-
if d.IsNewResource() {
85-
existing, err := client.Get(ctx, id)
86-
if err != nil {
87-
if !response.WasNotFound(existing.HttpResponse) {
88-
return fmt.Errorf("checking for presence of existing %s: %s", id, err)
89-
}
90-
}
91-
84+
existing, err := client.Get(ctx, id)
85+
if err != nil {
9286
if !response.WasNotFound(existing.HttpResponse) {
93-
return tf.ImportAsExistsError("azurerm_automation_dsc_nodeconfiguration", id.ID())
87+
return fmt.Errorf("checking for presence of existing %s: %s", id, err)
9488
}
9589
}
9690

97-
content := d.Get("content_embedded").(string)
98-
99-
// configuration name is always the first part of the dsc node configuration
100-
// e.g. webserver.prod or webserver.local will be associated to the dsc configuration webserver
101-
102-
configurationName := strings.Split(id.NodeConfigurationName, ".")[0]
103-
104-
contentSourceType := dscnodeconfiguration.ContentSourceTypeEmbeddedContent
91+
if !response.WasNotFound(existing.HttpResponse) {
92+
return tf.ImportAsExistsError("azurerm_automation_dsc_nodeconfiguration", id.ID())
93+
}
10594

10695
parameters := dscnodeconfiguration.DscNodeConfigurationCreateOrUpdateParameters{
10796
Properties: &dscnodeconfiguration.DscNodeConfigurationCreateOrUpdateParametersProperties{
10897
Source: dscnodeconfiguration.ContentSource{
109-
Type: &contentSourceType,
110-
Value: pointer.To(content),
98+
Type: pointer.To(dscnodeconfiguration.ContentSourceTypeEmbeddedContent),
99+
Value: pointer.To(d.Get("content_embedded").(string)),
111100
},
101+
// configuration name is always the first part of the dsc node configuration
102+
// e.g. webserver.prod or webserver.local will be associated to the dsc configuration webserver
112103
Configuration: dscnodeconfiguration.DscConfigurationAssociationProperty{
113-
Name: pointer.To(configurationName),
104+
Name: pointer.To(strings.Split(id.NodeConfigurationName, ".")[0]),
114105
},
115106
},
116107
Name: pointer.To(id.NodeConfigurationName),
117108
}
118109

119-
err := client.CreateOrUpdateThenPoll(ctx, id, parameters)
120-
if err != nil {
121-
return fmt.Errorf("creating/updating %s: %+v", id, err)
110+
if err := client.CreateOrUpdateThenPoll(ctx, id, parameters); err != nil {
111+
return fmt.Errorf("creating %s: %+v", id, err)
122112
}
123113

124114
d.SetId(id.ID())
125115

126116
return resourceAutomationDscNodeConfigurationRead(d, meta)
127117
}
128118

119+
func resourceAutomationDscNodeConfigurationUpdate(d *pluginsdk.ResourceData, meta interface{}) error {
120+
client := meta.(*clients.Client).Automation.DscNodeConfiguration
121+
ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d)
122+
defer cancel()
123+
124+
id, err := dscnodeconfiguration.ParseNodeConfigurationID(d.Id())
125+
if err != nil {
126+
return err
127+
}
128+
129+
// there is only one property that can be updated and is not force new: content_embedded
130+
// if content_embedded is changed, we need to update the dsc node configuration
131+
// otherwise we can just return as the resource is already in the desired state
132+
if d.HasChange("content_embedded") {
133+
parameters := dscnodeconfiguration.DscNodeConfigurationCreateOrUpdateParameters{
134+
Properties: &dscnodeconfiguration.DscNodeConfigurationCreateOrUpdateParametersProperties{
135+
Source: dscnodeconfiguration.ContentSource{
136+
Type: pointer.To(dscnodeconfiguration.ContentSourceTypeEmbeddedContent),
137+
// content_embedded is not returned by the API, so we get it from d.Get
138+
Value: pointer.To(d.Get("content_embedded").(string)),
139+
},
140+
// configuration name is always the first part of the dsc node configuration
141+
// e.g. webserver.prod or webserver.local will be associated to the dsc configuration webserver
142+
Configuration: dscnodeconfiguration.DscConfigurationAssociationProperty{
143+
Name: pointer.To(strings.Split(id.NodeConfigurationName, ".")[0]),
144+
},
145+
},
146+
Name: pointer.To(id.NodeConfigurationName),
147+
}
148+
149+
if err := client.CreateOrUpdateThenPoll(ctx, *id, parameters); err != nil {
150+
return fmt.Errorf("updating %s: %+v", *id, err)
151+
}
152+
}
153+
154+
return resourceAutomationDscNodeConfigurationRead(d, meta)
155+
}
156+
129157
func resourceAutomationDscNodeConfigurationRead(d *pluginsdk.ResourceData, meta interface{}) error {
130158
client := meta.(*clients.Client).Automation.DscNodeConfiguration
131159
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)

internal/services/automation/automation_dsc_nodeconfiguration_resource_test.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,30 @@ func TestAccAutomationDscNodeConfiguration_requiresImport(t *testing.T) {
4949
})
5050
}
5151

52+
func TestAccAutomationDscNodeConfiguration_update(t *testing.T) {
53+
data := acceptance.BuildTestData(t, "azurerm_automation_dsc_nodeconfiguration", "test")
54+
r := AutomationDscNodeConfigurationResource{}
55+
56+
data.ResourceTest(t, r, []acceptance.TestStep{
57+
{
58+
Config: r.basic(data),
59+
Check: acceptance.ComposeTestCheckFunc(
60+
check.That(data.ResourceName).ExistsInAzure(r),
61+
check.That(data.ResourceName).Key("configuration_name").HasValue("acctest"),
62+
),
63+
},
64+
data.ImportStep("content_embedded"),
65+
{
66+
Config: r.updated(data),
67+
Check: acceptance.ComposeTestCheckFunc(
68+
check.That(data.ResourceName).ExistsInAzure(r),
69+
check.That(data.ResourceName).Key("configuration_name").HasValue("acctest"),
70+
),
71+
},
72+
data.ImportStep("content_embedded"),
73+
})
74+
}
75+
5276
func (t AutomationDscNodeConfigurationResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
5377
id, err := dscnodeconfiguration.ParseNodeConfigurationID(state.ID)
5478
if err != nil {
@@ -136,3 +160,63 @@ resource "azurerm_automation_dsc_nodeconfiguration" "import" {
136160
}
137161
`, template)
138162
}
163+
164+
func (AutomationDscNodeConfigurationResource) updated(data acceptance.TestData) string {
165+
return fmt.Sprintf(`
166+
provider "azurerm" {
167+
features {}
168+
}
169+
170+
resource "azurerm_resource_group" "test" {
171+
name = "acctestRG-auto-%d"
172+
location = "%s"
173+
}
174+
175+
resource "azurerm_automation_account" "test" {
176+
name = "acctest-%d"
177+
location = azurerm_resource_group.test.location
178+
resource_group_name = azurerm_resource_group.test.name
179+
sku_name = "Basic"
180+
}
181+
182+
resource "azurerm_automation_dsc_configuration" "test" {
183+
name = "acctest"
184+
resource_group_name = azurerm_resource_group.test.name
185+
automation_account_name = azurerm_automation_account.test.name
186+
location = azurerm_resource_group.test.location
187+
content_embedded = "configuration acctest {}"
188+
}
189+
190+
resource "azurerm_automation_dsc_nodeconfiguration" "test" {
191+
name = "acctest.localhost"
192+
resource_group_name = azurerm_resource_group.test.name
193+
automation_account_name = azurerm_automation_account.test.name
194+
depends_on = [azurerm_automation_dsc_configuration.test]
195+
196+
content_embedded = <<mofcontent
197+
instance of MSFT_FileDirectoryConfiguration as $MSFT_FileDirectoryConfiguration1ref
198+
{
199+
TargetResourceID = "[File]bla";
200+
Ensure = "Present";
201+
Contents = "updated Content";
202+
DestinationPath = "c:\\updated.txt";
203+
ModuleName = "PSDesiredStateConfiguration";
204+
SourceInfo = "::3::9::file";
205+
ModuleVersion = "1.0";
206+
ConfigurationName = "bla";
207+
};
208+
instance of OMI_ConfigurationDocument
209+
{
210+
Version="2.0.0";
211+
MinimumCompatibleVersion = "1.0.0";
212+
CompatibleVersionAdditionalProperties= {"Omi_BaseResource:ConfigurationName"};
213+
Author="bogusAuthor";
214+
GenerationDate="06/15/2018 14:06:24";
215+
GenerationHost="bogusComputer";
216+
Name="acctest";
217+
};
218+
mofcontent
219+
220+
}
221+
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger)
222+
}

0 commit comments

Comments
 (0)