Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2a47980

Browse files
committed
fix: create new template version when tfvars change
1 parent ee9ac22 commit 2a47980

File tree

2 files changed

+313
-71
lines changed

2 files changed

+313
-71
lines changed

internal/provider/template_resource.go

+65-7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"encoding/json"
77
"fmt"
88
"io"
9+
"slices"
910
"strings"
1011

1112
"cdr.dev/slog"
@@ -1053,7 +1054,7 @@ func markActive(ctx context.Context, client *codersdk.Client, templateID uuid.UU
10531054
ID: versionID,
10541055
})
10551056
if err != nil {
1056-
return fmt.Errorf("Failed to update active template version: %s", err)
1057+
return fmt.Errorf("failed to update active template version: %s", err)
10571058
}
10581059
tflog.Info(ctx, "marked template version as active")
10591060
return nil
@@ -1231,8 +1232,9 @@ type LastVersionsByHash = map[string][]PreviousTemplateVersion
12311232
var LastVersionsKey = "last_versions"
12321233

12331234
type PreviousTemplateVersion struct {
1234-
ID uuid.UUID `json:"id"`
1235-
Name string `json:"name"`
1235+
ID uuid.UUID `json:"id"`
1236+
Name string `json:"name"`
1237+
TFVars map[string]string
12361238
}
12371239

12381240
type privateState interface {
@@ -1244,18 +1246,24 @@ func (v Versions) setPrivateState(ctx context.Context, ps privateState) (diags d
12441246
lv := make(LastVersionsByHash)
12451247
for _, version := range v {
12461248
vbh, ok := lv[version.DirectoryHash.ValueString()]
1249+
tfVars := make(map[string]string, len(version.TerraformVariables))
1250+
for _, tfVar := range version.TerraformVariables {
1251+
tfVars[tfVar.Name.ValueString()] = tfVar.Value.ValueString()
1252+
}
12471253
// Store the IDs and names of all versions with the same directory hash,
12481254
// in the order they appear
12491255
if ok {
12501256
lv[version.DirectoryHash.ValueString()] = append(vbh, PreviousTemplateVersion{
1251-
ID: version.ID.ValueUUID(),
1252-
Name: version.Name.ValueString(),
1257+
ID: version.ID.ValueUUID(),
1258+
Name: version.Name.ValueString(),
1259+
TFVars: tfVars,
12531260
})
12541261
} else {
12551262
lv[version.DirectoryHash.ValueString()] = []PreviousTemplateVersion{
12561263
{
1257-
ID: version.ID.ValueUUID(),
1258-
Name: version.Name.ValueString(),
1264+
ID: version.ID.ValueUUID(),
1265+
Name: version.Name.ValueString(),
1266+
TFVars: tfVars,
12591267
},
12601268
}
12611269
}
@@ -1269,6 +1277,13 @@ func (v Versions) setPrivateState(ctx context.Context, ps privateState) (diags d
12691277
}
12701278

12711279
func (planVersions Versions) reconcileVersionIDs(lv LastVersionsByHash, configVersions Versions) {
1280+
// We remove versions that we've matched from `lv`, so make a copy for
1281+
// resolving tfvar changes at the end.
1282+
fullLv := make(LastVersionsByHash)
1283+
for k, v := range lv {
1284+
fullLv[k] = slices.Clone(v)
1285+
}
1286+
12721287
for i := range planVersions {
12731288
prevList, ok := lv[planVersions[i].DirectoryHash.ValueString()]
12741289
// If not in state, mark as known after apply since we'll create a new version.
@@ -1308,4 +1323,47 @@ func (planVersions Versions) reconcileVersionIDs(lv LastVersionsByHash, configVe
13081323
lv[planVersions[i].DirectoryHash.ValueString()] = prevList[1:]
13091324
}
13101325
}
1326+
1327+
// If only the Terraform variables have changed,
1328+
// we need to create a new version with the new variables.
1329+
for i := range planVersions {
1330+
if !planVersions[i].ID.IsUnknown() {
1331+
prevs, ok := fullLv[planVersions[i].DirectoryHash.ValueString()]
1332+
if !ok {
1333+
continue
1334+
}
1335+
if tfVariablesChanged(prevs, &planVersions[i]) {
1336+
planVersions[i].ID = NewUUIDUnknown()
1337+
// We could always set the name to unknown here, to generate a
1338+
// random one (this is what the Web UI currently does when
1339+
// only updating tfvars).
1340+
// However, I think it'd be weird if the provider just started
1341+
// ignoring the name you set in the config, we'll instead
1342+
// require that users update the name if they update the tfvars.
1343+
if configVersions[i].Name.IsNull() {
1344+
planVersions[i].Name = types.StringUnknown()
1345+
}
1346+
}
1347+
}
1348+
}
1349+
}
1350+
1351+
func tfVariablesChanged(prevs []PreviousTemplateVersion, planned *TemplateVersion) bool {
1352+
for _, prev := range prevs {
1353+
if prev.ID == planned.ID.ValueUUID() {
1354+
// If the previous version has no TFVars, then it was created using
1355+
// an older provider version.
1356+
if prev.TFVars == nil {
1357+
return true
1358+
}
1359+
for _, tfVar := range planned.TerraformVariables {
1360+
if prev.TFVars[tfVar.Name.ValueString()] != tfVar.Value.ValueString() {
1361+
return true
1362+
}
1363+
}
1364+
return false
1365+
}
1366+
}
1367+
return true
1368+
13111369
}

0 commit comments

Comments
 (0)