Skip to content

Commit 5f05f86

Browse files
fix: set computed on namespace field (#784)
Signed-off-by: Blake Pettersson <[email protected]>
1 parent d23c21e commit 5f05f86

File tree

5 files changed

+109
-27
lines changed

5 files changed

+109
-27
lines changed

docs/data-sources/application.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,19 @@ data "argocd_application" "foo" {
3939

4040
Required:
4141

42-
- `name` (String) Name of the applications.argoproj.io, must be unique. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names
42+
- `name` (String) Name of the applications.argoproj.io, must be unique. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
4343

4444
Optional:
4545

4646
- `namespace` (String) Namespace of the applications.argoproj.io, must be unique. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
4747

4848
Read-Only:
4949

50-
- `annotations` (Map of String) An unstructured key value map stored with the cluster secret that may be used to store arbitrary metadata. More info: http://kubernetes.io/docs/user-guide/annotations
50+
- `annotations` (Map of String) An unstructured key value map stored with the applications.argoproj.io that may be used to store arbitrary metadata. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/
5151
- `generation` (Number) A sequence number representing a specific generation of the desired state.
52-
- `labels` (Map of String) Map of string keys and values that can be used to organize and categorize (scope and select) the cluster secret. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels
53-
- `resource_version` (String) An opaque value that represents the internal version of this applications.argoproj.io that can be used by clients to determine when applications.argoproj.io has changed. Read more: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
54-
- `uid` (String) The unique in time and space value for this applications.argoproj.io. More info: http://kubernetes.io/docs/user-guide/identifiers#uids
52+
- `labels` (Map of String) Map of string keys and values that can be used to organize and categorize (scope and select) the applications.argoproj.io. May match selectors of replication controllers and services. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels
53+
- `resource_version` (String) An opaque value that represents the internal version of this applications.argoproj.io that can be used by clients to determine when the applications.argoproj.io has changed. Read more: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
54+
- `uid` (String) The unique in time and space value for this applications.argoproj.io. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids
5555

5656

5757
<a id="nestedatt--spec"></a>

docs/resources/project.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -148,19 +148,19 @@ resource "argocd_project" "myproject" {
148148

149149
Required:
150150

151-
- `name` (String) Name of the appproject, must be unique. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names
151+
- `name` (String) Name of the appproject, must be unique. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
152152

153153
Optional:
154154

155-
- `annotations` (Map of String) An unstructured key value map stored with the cluster secret that may be used to store arbitrary metadata. More info: http://kubernetes.io/docs/user-guide/annotations
156-
- `labels` (Map of String) Map of string keys and values that can be used to organize and categorize (scope and select) the cluster secret. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels
155+
- `annotations` (Map of String) An unstructured key value map stored with the appproject that may be used to store arbitrary metadata. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/
156+
- `labels` (Map of String) Map of string keys and values that can be used to organize and categorize (scope and select) the appproject. May match selectors of replication controllers and services. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels
157157
- `namespace` (String) Namespace of the appproject, must be unique. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
158158

159159
Read-Only:
160160

161161
- `generation` (Number) A sequence number representing a specific generation of the desired state.
162-
- `resource_version` (String) An opaque value that represents the internal version of this appproject that can be used by clients to determine when appproject has changed. Read more: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
163-
- `uid` (String) The unique in time and space value for this appproject. More info: http://kubernetes.io/docs/user-guide/identifiers#uids
162+
- `resource_version` (String) An opaque value that represents the internal version of this appproject that can be used by clients to determine when the appproject has changed. Read more: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
163+
- `uid` (String) The unique in time and space value for this appproject. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids
164164

165165

166166
<a id="nestedblock--spec"></a>

internal/provider/model_metadata.go

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func objectMetaSchemaAttribute(objectName string, computed bool) schema.Attribut
3131
Required: true,
3232
Attributes: map[string]schema.Attribute{
3333
"name": schema.StringAttribute{
34-
MarkdownDescription: fmt.Sprintf("Name of the %s, must be unique. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names", objectName),
34+
MarkdownDescription: fmt.Sprintf("Name of the %s, must be unique. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", objectName),
3535
Required: true,
3636
PlanModifiers: []planmodifier.String{
3737
stringplanmodifier.RequiresReplace(),
@@ -52,7 +52,7 @@ func objectMetaSchemaAttribute(objectName string, computed bool) schema.Attribut
5252
},
5353
},
5454
"annotations": schema.MapAttribute{
55-
MarkdownDescription: "An unstructured key value map stored with the cluster secret that may be used to store arbitrary metadata. More info: http://kubernetes.io/docs/user-guide/annotations",
55+
MarkdownDescription: fmt.Sprintf("An unstructured key value map stored with the %s that may be used to store arbitrary metadata. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/", objectName),
5656
Computed: computed,
5757
Optional: !computed,
5858
ElementType: types.StringType,
@@ -61,7 +61,7 @@ func objectMetaSchemaAttribute(objectName string, computed bool) schema.Attribut
6161
},
6262
},
6363
"labels": schema.MapAttribute{
64-
MarkdownDescription: "Map of string keys and values that can be used to organize and categorize (scope and select) the cluster secret. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels",
64+
MarkdownDescription: fmt.Sprintf("Map of string keys and values that can be used to organize and categorize (scope and select) the %s. May match selectors of replication controllers and services. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels", objectName),
6565
Computed: computed,
6666
Optional: !computed,
6767
ElementType: types.StringType,
@@ -74,18 +74,18 @@ func objectMetaSchemaAttribute(objectName string, computed bool) schema.Attribut
7474
Computed: true,
7575
},
7676
"resource_version": schema.StringAttribute{
77-
MarkdownDescription: fmt.Sprintf("An opaque value that represents the internal version of this %s that can be used by clients to determine when %s has changed. Read more: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency", objectName, objectName),
77+
MarkdownDescription: fmt.Sprintf("An opaque value that represents the internal version of this %s that can be used by clients to determine when the %s has changed. Read more: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency", objectName, objectName),
7878
Computed: true,
7979
},
8080
"uid": schema.StringAttribute{
81-
MarkdownDescription: fmt.Sprintf("The unique in time and space value for this %s. More info: http://kubernetes.io/docs/user-guide/identifiers#uids", objectName),
81+
MarkdownDescription: fmt.Sprintf("The unique in time and space value for this %s. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids", objectName),
8282
Computed: true,
8383
},
8484
},
8585
}
8686
}
8787

88-
func objectMetaSchemaListBlock(objectName string, computed bool) schema.Block {
88+
func objectMetaSchemaListBlock(objectName string) schema.Block {
8989
return schema.ListNestedBlock{
9090
MarkdownDescription: "Standard Kubernetes object metadata. For more info see the [Kubernetes reference](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#metadata).",
9191
Validators: []validator.List{
@@ -96,7 +96,7 @@ func objectMetaSchemaListBlock(objectName string, computed bool) schema.Block {
9696
NestedObject: schema.NestedBlockObject{
9797
Attributes: map[string]schema.Attribute{
9898
"name": schema.StringAttribute{
99-
MarkdownDescription: fmt.Sprintf("Name of the %s, must be unique. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names", objectName),
99+
MarkdownDescription: fmt.Sprintf("Name of the %s, must be unique. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", objectName),
100100
Required: true,
101101
PlanModifiers: []planmodifier.String{
102102
stringplanmodifier.RequiresReplace(),
@@ -108,7 +108,7 @@ func objectMetaSchemaListBlock(objectName string, computed bool) schema.Block {
108108
"namespace": schema.StringAttribute{
109109
MarkdownDescription: fmt.Sprintf("Namespace of the %s, must be unique. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/", objectName),
110110
Optional: true,
111-
Computed: computed,
111+
Computed: true,
112112
PlanModifiers: []planmodifier.String{
113113
stringplanmodifier.RequiresReplace(),
114114
},
@@ -117,18 +117,16 @@ func objectMetaSchemaListBlock(objectName string, computed bool) schema.Block {
117117
},
118118
},
119119
"annotations": schema.MapAttribute{
120-
MarkdownDescription: "An unstructured key value map stored with the cluster secret that may be used to store arbitrary metadata. More info: http://kubernetes.io/docs/user-guide/annotations",
121-
Computed: computed,
122-
Optional: !computed,
120+
MarkdownDescription: fmt.Sprintf("An unstructured key value map stored with the %s that may be used to store arbitrary metadata. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/", objectName),
121+
Optional: true,
123122
ElementType: types.StringType,
124123
Validators: []validator.Map{
125124
validators.MetadataAnnotations(),
126125
},
127126
},
128127
"labels": schema.MapAttribute{
129-
MarkdownDescription: "Map of string keys and values that can be used to organize and categorize (scope and select) the cluster secret. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels",
130-
Computed: computed,
131-
Optional: !computed,
128+
MarkdownDescription: fmt.Sprintf("Map of string keys and values that can be used to organize and categorize (scope and select) the %s. May match selectors of replication controllers and services. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels", objectName),
129+
Optional: true,
132130
ElementType: types.StringType,
133131
Validators: []validator.Map{
134132
validators.MetadataLabels(),
@@ -139,11 +137,11 @@ func objectMetaSchemaListBlock(objectName string, computed bool) schema.Block {
139137
Computed: true,
140138
},
141139
"resource_version": schema.StringAttribute{
142-
MarkdownDescription: fmt.Sprintf("An opaque value that represents the internal version of this %s that can be used by clients to determine when %s has changed. Read more: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency", objectName, objectName),
140+
MarkdownDescription: fmt.Sprintf("An opaque value that represents the internal version of this %s that can be used by clients to determine when the %s has changed. Read more: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency", objectName, objectName),
143141
Computed: true,
144142
},
145143
"uid": schema.StringAttribute{
146-
MarkdownDescription: fmt.Sprintf("The unique in time and space value for this %s. More info: http://kubernetes.io/docs/user-guide/identifiers#uids", objectName),
144+
MarkdownDescription: fmt.Sprintf("The unique in time and space value for this %s. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids", objectName),
147145
Computed: true,
148146
},
149147
},

internal/provider/model_project.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ type syncWindowModel struct {
8787

8888
func projectSchemaBlocks() map[string]schema.Block {
8989
return map[string]schema.Block{
90-
"metadata": objectMetaSchemaListBlock("appproject", false),
90+
"metadata": objectMetaSchemaListBlock("appproject"),
9191
"spec": schema.ListNestedBlock{
9292
Description: "ArgoCD AppProject spec.",
9393
Validators: []validator.List{
@@ -392,6 +392,12 @@ func newProjectSpec(spec *v1alpha1.AppProjectSpec) projectSpecModel {
392392
Description: types.StringValue(spec.Description),
393393
}
394394

395+
if spec.Description != "" {
396+
ps.Description = types.StringValue(spec.Description)
397+
} else {
398+
ps.Description = types.StringNull()
399+
}
400+
395401
// Convert source repos
396402
if len(spec.SourceRepos) > 0 {
397403
ps.SourceRepos = make([]types.String, len(spec.SourceRepos))

internal/provider/resource_project_test.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1471,3 +1471,81 @@ resource "argocd_project" "migration" {
14711471
}
14721472
`, name)
14731473
}
1474+
1475+
// TestAccArgoCDProject_ProviderUpgradeStateMigration_WithoutNamespace tests the specific
1476+
// case reported in issue #783 where projects created without an explicit namespace field
1477+
// in v7.12.1 cause forced replacement when upgrading to v7.12.3+.
1478+
// The namespace should be computed from the API response without causing drift.
1479+
func TestAccArgoCDProject_ProviderUpgradeStateMigration_WithoutNamespace(t *testing.T) {
1480+
name := acctest.RandomWithPrefix("test-acc-migrate-no-ns")
1481+
config := testAccArgoCDProjectForStateMigrationWithoutNamespace(name)
1482+
1483+
resource.Test(t, resource.TestCase{
1484+
Steps: []resource.TestStep{
1485+
{
1486+
// Step 1: Create project using old SDK-based provider (v7.12.1)
1487+
// without specifying namespace in metadata (this is the key scenario)
1488+
ExternalProviders: map[string]resource.ExternalProvider{
1489+
"argocd": {
1490+
VersionConstraint: "7.12.1",
1491+
Source: "argoproj-labs/argocd",
1492+
},
1493+
},
1494+
Config: config,
1495+
Check: resource.ComposeTestCheckFunc(
1496+
resource.TestCheckResourceAttr("argocd_project.tech", "metadata.0.name", name),
1497+
resource.TestCheckResourceAttrSet("argocd_project.tech", "metadata.0.uid"),
1498+
),
1499+
},
1500+
{
1501+
// Step 2: Upgrade to new framework-based provider
1502+
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
1503+
Config: config,
1504+
Check: resource.ComposeTestCheckFunc(
1505+
resource.TestCheckResourceAttr("argocd_project.tech", "metadata.0.name", name),
1506+
resource.TestCheckResourceAttr("argocd_project.tech", "spec.0.source_repos.#", "1"),
1507+
resource.TestCheckResourceAttr("argocd_project.tech", "spec.0.destination.#", "1"),
1508+
resource.TestCheckResourceAttr("argocd_project.tech", "spec.0.cluster_resource_whitelist.#", "1"),
1509+
// Namespace should be computed from API, not forcing replacement
1510+
resource.TestCheckResourceAttr("argocd_project.tech", "metadata.0.namespace", "argocd"),
1511+
),
1512+
},
1513+
{
1514+
// Step 3: Verify no unexpected plan changes after migration (issue #783)
1515+
// This should NOT show a forced replacement due to namespace changing
1516+
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
1517+
Config: config,
1518+
ConfigPlanChecks: resource.ConfigPlanChecks{
1519+
PreApply: []plancheck.PlanCheck{
1520+
plancheck.ExpectEmptyPlan(),
1521+
},
1522+
},
1523+
},
1524+
},
1525+
})
1526+
}
1527+
1528+
func testAccArgoCDProjectForStateMigrationWithoutNamespace(name string) string {
1529+
return fmt.Sprintf(`
1530+
resource "argocd_project" "tech" {
1531+
metadata {
1532+
name = "%s"
1533+
# NOTE: namespace is intentionally NOT specified here to test issue #783
1534+
}
1535+
1536+
spec {
1537+
source_repos = ["*"]
1538+
1539+
destination {
1540+
server = "https://kubernetes.default.svc"
1541+
namespace = "*"
1542+
}
1543+
1544+
cluster_resource_whitelist {
1545+
group = "*"
1546+
kind = "*"
1547+
}
1548+
}
1549+
}
1550+
`, name)
1551+
}

0 commit comments

Comments
 (0)