Skip to content

Commit

Permalink
Fix argocd_project orphaned_resources v0 to v1 migration and permadiff (
Browse files Browse the repository at this point in the history
  • Loading branch information
oboukili authored Feb 9, 2021
1 parent c968929 commit d818ac6
Show file tree
Hide file tree
Showing 7 changed files with 350 additions and 141 deletions.
9 changes: 7 additions & 2 deletions argocd/resource_argocd_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,20 @@ func resourceArgoCDProject() *schema.Resource {
},
Schema: map[string]*schema.Schema{
"metadata": metadataSchema("appprojects.argoproj.io"),
"spec": projectSpecSchemaV1(),
"spec": projectSpecSchemaV2(),
},
SchemaVersion: 1,
SchemaVersion: 2,
StateUpgraders: []schema.StateUpgrader{
{
Type: resourceArgoCDProjectV0().CoreConfigSchema().ImpliedType(),
Upgrade: resourceArgoCDProjectStateUpgradeV0,
Version: 0,
},
{
Type: resourceArgoCDProjectV1().CoreConfigSchema().ImpliedType(),
Upgrade: resourceArgoCDProjectStateUpgradeV1,
Version: 1,
},
},
}
}
Expand Down
2 changes: 1 addition & 1 deletion argocd/resource_argocd_project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ func TestAccArgoCDProject(t *testing.T) {
}

func TestAccArgoCDProject_tokensCoexistence(t *testing.T) {

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
ExpectNonEmptyPlan: true,
Config: testAccArgoCDProjectCoexistenceWithTokenResource(
"test-acc-"+acctest.RandString(10),
4,
Expand Down
241 changes: 215 additions & 26 deletions argocd/schema_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package argocd
import (
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"reflect"
)

func projectSpecSchemaV0() *schema.Schema {
Expand Down Expand Up @@ -341,26 +342,78 @@ func projectSpecSchemaV1() *schema.Schema {
}
}

func resourceArgoCDProjectV0() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"metadata": metadataSchema("appprojects.argoproj.io"),
"spec": projectSpecSchemaV0(),
},
}
}

func resourceArgoCDProjectStateUpgradeV0(rawState map[string]interface{}, _ interface{}) (map[string]interface{}, error) {
spec := rawState["spec"].([]map[string]interface{})
if len(spec) > 0 {
if orphanedResources, ok := spec[0]["orphaned_resources"]; ok {
switch orphanedResources.(type) {

// <= v0.4.8
case map[string]bool:
warn := orphanedResources.(map[string]bool)["warn"]
newOrphanedResources := schema.NewSet(
schema.HashResource(&schema.Resource{
func projectSpecSchemaV2() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
MinItems: 1,
MaxItems: 1,
Description: "ArgoCD App project resource specs. Required attributes: destination, source_repos.",
Required: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cluster_resource_whitelist": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"group": {
Type: schema.TypeString,
ValidateFunc: validateGroupName,
Optional: true,
},
"kind": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"destination": {
Type: schema.TypeSet,
Required: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"server": {
Type: schema.TypeString,
Optional: true,
},
"namespace": {
Type: schema.TypeString,
Required: true,
},
"name": {
Type: schema.TypeString,
Optional: true,
Description: "Name of the destination cluster which can be used instead of server.",
},
},
},
},
"namespace_resource_blacklist": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"group": {
Type: schema.TypeString,
Optional: true,
},
"kind": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
"orphaned_resources": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"warn": {
Type: schema.TypeBool,
Expand Down Expand Up @@ -388,15 +441,151 @@ func resourceArgoCDProjectStateUpgradeV0(rawState map[string]interface{}, _ inte
},
},
},
}),
[]interface{}{map[string]interface{}{"warn": warn}},
)
rawState["spec"].([]map[string]interface{})[0]["orphaned_resources"] = newOrphanedResources
},
},
"role": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"description": {
Type: schema.TypeString,
Optional: true,
},
"groups": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"name": {
Type: schema.TypeString,
ValidateFunc: validateRoleName,
Required: true,
},
"policies": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
},
},
"source_repos": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"signature_keys": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"sync_window": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"applications": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"clusters": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"duration": {
Type: schema.TypeString,
ValidateFunc: validateSyncWindowDuration,
Optional: true,
},
"kind": {
Type: schema.TypeString,
ValidateFunc: validateSyncWindowKind,
Optional: true,
},
"manual_sync": {
Type: schema.TypeBool,
Optional: true,
},
"namespaces": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"schedule": {
Type: schema.TypeString,
ValidateFunc: validateSyncWindowSchedule,
Optional: true,
},
},
},
},
},
},
}
}

func resourceArgoCDProjectV0() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"metadata": metadataSchema("appprojects.argoproj.io"),
"spec": projectSpecSchemaV0(),
},
}
}

func resourceArgoCDProjectV1() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"metadata": metadataSchema("appprojects.argoproj.io"),
"spec": projectSpecSchemaV1(),
},
}
}

func resourceArgoCDProjectStateUpgradeV0(rawState map[string]interface{}, _ interface{}) (map[string]interface{}, error) {
_spec := rawState["spec"]
if len(_spec.([]interface{})) > 0 {
spec := _spec.([]interface{})[0]
if orphanedResources, ok := spec.(map[string]interface{})["orphaned_resources"]; ok {
switch orphanedResources.(type) {
// <= v0.4.8 with nil orphaned_resources map
case map[string]interface{}:
warn := orphanedResources.(map[string]interface{})["warn"]
newOrphanedResources := []interface{}{map[string]interface{}{"warn": warn}}
rawState["spec"].([]interface{})[0].(map[string]interface{})["orphaned_resources"] = newOrphanedResources

// >= v0.5.0 <= v1.1.0
// <= v0.4.8 with non-nil orphaned_resources map
case map[string]bool:
warn := orphanedResources.(map[string]bool)["warn"]
newOrphanedResources := []interface{}{map[string]bool{"warn": warn}}
rawState["spec"].([]interface{})[0].(map[string]interface{})["orphaned_resources"] = newOrphanedResources

// >= v0.5.0 <= v1.1.2 (should not happen)
case *schema.Set:
return nil, fmt.Errorf("error during state migration v0 to v1, unsupported type for 'orphaned_resources': %s", reflect.TypeOf(orphanedResources))
default:
return nil, fmt.Errorf("error during state migration v0 to v1, unsupported type for 'orphaned_resources': %s", reflect.TypeOf(orphanedResources))
}
}
}
return rawState, nil
}

func resourceArgoCDProjectStateUpgradeV1(rawState map[string]interface{}, _ interface{}) (map[string]interface{}, error) {
_spec := rawState["spec"]
if len(_spec.([]interface{})) > 0 {
spec := _spec.([]interface{})[0]
if orphanedResources, ok := spec.(map[string]interface{})["orphaned_resources"]; ok {
switch orphanedResources.(type) {
case []interface{}:
// >= v0.5.0 <= v1.1.2
case *schema.Set:
rawState["spec"].([]interface{})[0].(map[string]interface{})["orphaned_resources"] = orphanedResources.(*schema.Set).List()
default:
return nil, fmt.Errorf("error during state migration v0 to v1, unsupported type for 'orphaned_resources': %s", orphanedResources)
return nil, fmt.Errorf("error during state migration v1 to v2, unsupported type for 'orphaned_resources': %s", reflect.TypeOf(orphanedResources))
}
}
}
Expand Down
Loading

0 comments on commit d818ac6

Please sign in to comment.