Skip to content

Commit

Permalink
initial work to add opaqu type
Browse files Browse the repository at this point in the history
Signed-off-by: Will Arroyo <warroyo7199008@gmail.com>
  • Loading branch information
warroyo committed Mar 18, 2024
1 parent 4a303a9 commit 9ca126c
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 53 deletions.
10 changes: 7 additions & 3 deletions internal/resources/kubernetessecret/data_source_secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,14 @@ func dataSourceSecretRead(ctx context.Context, d *schema.ResourceData, m interfa
d.SetId(secretDataFromServer.UID)

var password string
var opaqueData map[string]interface{}

if _, ok := d.GetOk(spec.SpecKey); ok {
if _, ok := d.GetOk(helper.GetFirstElementOf(spec.SpecKey, spec.DockerConfigjsonKey, spec.PasswordKey)); ok {
password, _ = (d.Get(helper.GetFirstElementOf(spec.SpecKey, spec.DockerConfigjsonKey, spec.PasswordKey))).(string)
}
if opData, ok := d.GetOk(helper.GetFirstElementOf(spec.SpecKey, spec.OpaqueKey)); ok && opData != nil {
opaqueData = opData.(map[string]interface{})
}

if d.Get(ExportKey).(bool) {
if secretDataFromServer.secretExportErr != nil || secretDataFromServer.secretExportRespNil {
Expand Down Expand Up @@ -121,13 +125,13 @@ func dataSourceSecretRead(ctx context.Context, d *schema.ResourceData, m interfa

switch scopedFullnameData.Scope {
case commonscope.ClusterScope:
flattenedSpec = spec.FlattenSpecForClusterScope(ctx, secretDataFromServer.atomicSpec, password)
flattenedSpec = spec.FlattenSpecForClusterScope(secretDataFromServer.atomicSpec, password, opaqueData)
flattenedStatus = status.FlattenStatusForClusterScope(secretDataFromServer.clusterScopeStatus)
case commonscope.ClusterGroupScope:
clusterGroupScopeSpec := &secretclustergroupmodel.VmwareTanzuManageV1alpha1ClustergroupNamespaceSecretSpec{
AtomicSpec: secretDataFromServer.atomicSpec,
}
flattenedSpec = spec.FlattenSpecForClusterGroupScope(ctx, clusterGroupScopeSpec, password)
flattenedSpec = spec.FlattenSpecForClusterGroupScope(clusterGroupScopeSpec, password, opaqueData)
flattenedStatus = status.FlattenStatusForClusterGroupScope(secretDataFromServer.clusterGroupScopeStatus)
}

Expand Down
9 changes: 5 additions & 4 deletions internal/resources/kubernetessecret/resource_secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func ResourceSecret() *schema.Resource {
Schema: getResourceSchema(),
CustomizeDiff: customdiff.All(
schema.CustomizeDiffFunc(commonscope.ValidateScope(scope.ScopesAllowed[:])),
spec.ValidateInput,
),
}
}
Expand Down Expand Up @@ -138,7 +139,7 @@ func resourceSecretCreate(ctx context.Context, d *schema.ResourceData, m interfa
Secret: &clustersecretmodel.VmwareTanzuManageV1alpha1ClusterNamespaceSecret{
FullName: scopedFullnameData.FullnameCluster,
Meta: meta,
Spec: spec.ConstructSpecForClusterScope(ctx, d),
Spec: spec.ConstructSpecForClusterScope(d),
},
}

Expand All @@ -155,7 +156,7 @@ func resourceSecretCreate(ctx context.Context, d *schema.ResourceData, m interfa
Secret: &clustergroupsecretmodel.VmwareTanzuManageV1alpha1ClustergroupNamespaceSecretSecret{
FullName: scopedFullnameData.FullnameClusterGroup,
Meta: meta,
Spec: spec.ConstructSpecForClusterGroupScope(ctx, d),
Spec: spec.ConstructSpecForClusterGroupScope(d),
},
}

Expand Down Expand Up @@ -349,9 +350,9 @@ func updateCheckForSpec(ctx context.Context, d *schema.ResourceData, atomicSpec

switch scope {
case commonscope.ClusterScope:
secretSpec = spec.ConstructSpecForClusterScope(ctx, d)
secretSpec = spec.ConstructSpecForClusterScope(d)
case commonscope.ClusterGroupScope:
clusterGroupScopeSpec := spec.ConstructSpecForClusterGroupScope(ctx, d)
clusterGroupScopeSpec := spec.ConstructSpecForClusterGroupScope(d)
secretSpec = clusterGroupScopeSpec.AtomicSpec
}

Expand Down
10 changes: 4 additions & 6 deletions internal/resources/kubernetessecret/spec/cluster_group_scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ SPDX-License-Identifier: MPL-2.0
package spec

import (
"context"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

secertclustergroupmodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/kubernetessecret/clustergroup"
)

func ConstructSpecForClusterGroupScope(ctx context.Context, d *schema.ResourceData) (spec *secertclustergroupmodel.VmwareTanzuManageV1alpha1ClustergroupNamespaceSecretSpec) {
func ConstructSpecForClusterGroupScope(d *schema.ResourceData) (spec *secertclustergroupmodel.VmwareTanzuManageV1alpha1ClustergroupNamespaceSecretSpec) {
value, ok := d.GetOk(SpecKey)
if !ok {
return spec
Expand All @@ -26,15 +24,15 @@ func ConstructSpecForClusterGroupScope(ctx context.Context, d *schema.ResourceDa
}

spec = &secertclustergroupmodel.VmwareTanzuManageV1alpha1ClustergroupNamespaceSecretSpec{}
spec.AtomicSpec = ConstructSpecForClusterScope(ctx, d)
spec.AtomicSpec = ConstructSpecForClusterScope(d)

return spec
}

func FlattenSpecForClusterGroupScope(ctx context.Context, spec *secertclustergroupmodel.VmwareTanzuManageV1alpha1ClustergroupNamespaceSecretSpec, password string) (data []interface{}) {
func FlattenSpecForClusterGroupScope(spec *secertclustergroupmodel.VmwareTanzuManageV1alpha1ClustergroupNamespaceSecretSpec, password string, opaqueData map[string]interface{}) (data []interface{}) {
if spec == nil || spec.AtomicSpec == nil {
return data
}

return FlattenSpecForClusterScope(ctx, spec.AtomicSpec, password)
return FlattenSpecForClusterScope(spec.AtomicSpec, password, opaqueData)
}
50 changes: 17 additions & 33 deletions internal/resources/kubernetessecret/spec/cluster_scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,18 @@ SPDX-License-Identifier: MPL-2.0
package spec

import (
"context"
"encoding/base64"
"encoding/json"
"fmt"

"github.com/hashicorp/terraform-plugin-log/tflog"

"github.com/go-openapi/strfmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/common"

secretmodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/kubernetessecret/cluster"
)

func ConstructSpecForClusterScope(ctx context.Context, d *schema.ResourceData) (spec *secretmodel.VmwareTanzuManageV1alpha1ClusterNamespaceSecretSpec) {
func ConstructSpecForClusterScope(d *schema.ResourceData) (spec *secretmodel.VmwareTanzuManageV1alpha1ClusterNamespaceSecretSpec) {
spec = &secretmodel.VmwareTanzuManageV1alpha1ClusterNamespaceSecretSpec{}

value, ok := d.GetOk(SpecKey)
Expand Down Expand Up @@ -68,25 +65,21 @@ func ConstructSpecForClusterScope(ctx context.Context, d *schema.ResourceData) (
}

if v, ok := specData[OpaqueKey]; ok {

Check failure on line 67 in internal/resources/kubernetessecret/spec/cluster_scope.go

View workflow job for this annotation

GitHub Actions / lint

unnecessary leading newline (whitespace)
tflog.Info(ctx, "MAde it to opaque")

opaqueData := common.GetTypeStringMapData(v.(map[string]interface{}))
if len(opaqueData) != 0 {
spec.SecretType = secretmodel.NewVmwareTanzuManageV1alpha1ClusterNamespaceSecretType(secretmodel.VmwareTanzuManageV1alpha1ClusterNamespaceSecretTypeSECRETTYPEOPAQUE)
tflog.Info(ctx, fmt.Sprintf("testing %v", opaqueData))

encodedData := getEncodedOpaqueData(ctx, opaqueData)
tflog.Info(ctx, fmt.Sprintf("%v", encodedData))
encodedData := getEncodedOpaqueData(opaqueData)
spec.Data = encodedData
}

Check failure on line 76 in internal/resources/kubernetessecret/spec/cluster_scope.go

View workflow job for this annotation

GitHub Actions / lint

unnecessary trailing newline (whitespace)
}

Check failure on line 77 in internal/resources/kubernetessecret/spec/cluster_scope.go

View workflow job for this annotation

GitHub Actions / lint

block should not end with a whitespace (or comment) (wsl)

tflog.Info(ctx, "returning")
return spec
}

func FlattenSpecForClusterScope(ctx context.Context, spec *secretmodel.VmwareTanzuManageV1alpha1ClusterNamespaceSecretSpec, pass string) (data []interface{}) {
func FlattenSpecForClusterScope(spec *secretmodel.VmwareTanzuManageV1alpha1ClusterNamespaceSecretSpec, pass string, opaqueData map[string]interface{}) (data []interface{}) {
if spec == nil {
return data
}
Expand Down Expand Up @@ -126,15 +119,8 @@ func FlattenSpecForClusterScope(ctx context.Context, spec *secretmodel.VmwareTan
}

if *spec.SecretType == *secretmodel.NewVmwareTanzuManageV1alpha1ClusterNamespaceSecretType(secretmodel.VmwareTanzuManageV1alpha1ClusterNamespaceSecretTypeSECRETTYPEOPAQUE) {

Check failure on line 121 in internal/resources/kubernetessecret/spec/cluster_scope.go

View workflow job for this annotation

GitHub Actions / lint

unnecessary leading newline (whitespace)
tflog.Info(ctx, "secret type opaque")
secretData := spec.Data
decodedData, err := getDecodedOpaqueData(secretData)
if err != nil {
return data
}
tflog.Info(ctx, fmt.Sprintf("%v", decodedData))

flattenSpecData[OpaqueKey] = []interface{}{decodedData}
flattenSpecData[OpaqueKey] = opaqueData
}

return []interface{}{flattenSpecData}
Expand Down Expand Up @@ -169,27 +155,25 @@ func getDecodedSpecData(data strfmt.Base64) (*dockerConfigJSON, error) {
return dockerConfigJSON, nil
}

func getEncodedOpaqueData(ctx context.Context, data map[string]string) map[string]strfmt.Base64 {
func getEncodedOpaqueData(data map[string]string) map[string]strfmt.Base64 {
encoded := make(map[string]strfmt.Base64)

for k, v := range data {
tflog.Info(ctx, v)
encoded[k] = strfmt.Base64(v)
tflog.Info(ctx, string(encoded[k]))
}

return encoded
}

func getDecodedOpaqueData(data map[string]strfmt.Base64) (map[string]string, error) {
decoded := make(map[string]string)
for k, v := range data {
decodedValue, err := base64.StdEncoding.DecodeString(v.String())
if err != nil {
return nil, err
}
decoded[k] = string(decodedValue)
}

return decoded, nil
}
// func getDecodedOpaqueData(data map[string]strfmt.Base64) (map[string]string, error) {
// decoded := make(map[string]string)
// for k, v := range data {
// decodedValue, err := base64.StdEncoding.DecodeString(v.String())
// if err != nil {
// return nil, err
// }
// decoded[k] = string(decodedValue)
// }

// return decoded, nil
// }
55 changes: 52 additions & 3 deletions internal/resources/kubernetessecret/spec/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@ SPDX-License-Identifier: MPL-2.0
package spec

import (
"context"
"fmt"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"

"github.com/vmware/terraform-provider-tanzu-mission-control/internal/helper"
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/gitrepository/spec"
)

const (
Expand Down Expand Up @@ -38,11 +43,14 @@ var SecretSpec = &schema.Schema{
Type: schema.TypeMap,
Description: "SecretType definition - SECRET_TYPE_OPAQUE, Kubernetes secrets type.",
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Sensitive: true,

Elem: &schema.Schema{Type: schema.TypeString},
},
DockerConfigjsonKey: {
Type: schema.TypeList,
Optional: true,
Type: schema.TypeList,
Optional: true,

Description: "SecretType definition - SECRET_TYPE_DOCKERCONFIGJSON, Kubernetes secrets type.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
Expand Down Expand Up @@ -97,3 +105,44 @@ func HasSpecChanged(d *schema.ResourceData) bool {

return updateRequired
}

func ValidateInput(ctx context.Context, diff *schema.ResourceDiff, i interface{}) error {
value, ok := diff.GetOk(spec.SpecKey)
if !ok {
return fmt.Errorf("spec: %v is not valid: minimum one valid spec block is required", value)
}

data, _ := value.([]interface{})

specData := data[0].(map[string]interface{})
secretTypes := []string{
OpaqueKey,
DockerConfigjsonKey,
}
secretTypesFound := make([]string, 0)

for _, secret := range secretTypes {
if secretData, ok := specData[secret]; ok {
if secret == OpaqueKey {
converted := secretData.(map[string]interface{})
if len(converted) != 0 {
secretTypesFound = append(secretTypesFound, secret)
}
}
if secret == DockerConfigjsonKey {
converted := secretData.([]interface{})
if len(converted) != 0 {
secretTypesFound = append(secretTypesFound, secret)
}
}

Check failure on line 138 in internal/resources/kubernetessecret/spec/spec.go

View workflow job for this annotation

GitHub Actions / lint

unnecessary trailing newline (whitespace)
}

Check failure on line 139 in internal/resources/kubernetessecret/spec/spec.go

View workflow job for this annotation

GitHub Actions / lint

block should not end with a whitespace (or comment) (wsl)
}

if len(secretTypesFound) == 0 {
return fmt.Errorf("no valid spec block found: minimum one valid secret block is required among: %v", strings.Join(secretTypes[:], `, `))

Check failure on line 143 in internal/resources/kubernetessecret/spec/spec.go

View workflow job for this annotation

GitHub Actions / lint

unslice: could simplify secretTypes[:] to secretTypes (gocritic)
} else if len(secretTypesFound) > 1 {
return fmt.Errorf("found secret blocks: %v are not valid: maximum one valid secret block is allowed", strings.Join(secretTypesFound, `, `))
}
return nil
}
46 changes: 42 additions & 4 deletions internal/resources/kubernetessecret/spec/spec_flatten_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestFlattenClusterScopeSpec(t *testing.T) {
expected: nil,
},
{
description: "normal scenario with all values under spec",
description: "registry secret test",
input: &secretclustermodel.VmwareTanzuManageV1alpha1ClusterNamespaceSecretSpec{
SecretType: secretclustermodel.NewVmwareTanzuManageV1alpha1ClusterNamespaceSecretType(secretclustermodel.VmwareTanzuManageV1alpha1ClusterNamespaceSecretTypeSECRETTYPEDOCKERCONFIGJSON),
Data: map[string]strfmt.Base64{
Expand All @@ -48,12 +48,30 @@ func TestFlattenClusterScopeSpec(t *testing.T) {
},
},
},
{
description: "opaque secret test",
input: &secretclustermodel.VmwareTanzuManageV1alpha1ClusterNamespaceSecretSpec{
SecretType: secretclustermodel.NewVmwareTanzuManageV1alpha1ClusterNamespaceSecretType(secretclustermodel.VmwareTanzuManageV1alpha1ClusterNamespaceSecretTypeSECRETTYPEOPAQUE),
Data: map[string]strfmt.Base64{
"username": []byte(`myuser`),
"password": []byte(`somelongpassword`),
},
},
expected: []interface{}{
map[string]interface{}{
OpaqueKey: map[string]interface{}{
"username": "myuser",
"password": "somelongpassword",
},
},
},
},
}

for _, each := range cases {
test := each
t.Run(test.description, func(t *testing.T) {
actual := FlattenSpecForClusterScope(test.input, "somepassword")
actual := FlattenSpecForClusterScope(test.input, "somepassword", map[string]interface{}{"username": "myuser", "password": "somelongpassword"})
require.Equal(t, test.expected, actual)
})
}
Expand All @@ -73,7 +91,7 @@ func TestFlattenClusterGroupScopeSpec(t *testing.T) {
expected: nil,
},
{
description: "normal scenario with all values under spec",
description: "normal scenario for registry secret with all values under spec",
input: &secretclustergroupmodel.VmwareTanzuManageV1alpha1ClustergroupNamespaceSecretSpec{
AtomicSpec: &secretclustermodel.VmwareTanzuManageV1alpha1ClusterNamespaceSecretSpec{
SecretType: secretclustermodel.NewVmwareTanzuManageV1alpha1ClusterNamespaceSecretType(secretclustermodel.VmwareTanzuManageV1alpha1ClusterNamespaceSecretTypeSECRETTYPEDOCKERCONFIGJSON),
Expand All @@ -94,12 +112,32 @@ func TestFlattenClusterGroupScopeSpec(t *testing.T) {
},
},
},
{
description: "normal scenario for opaque secret with all values under spec",
input: &secretclustergroupmodel.VmwareTanzuManageV1alpha1ClustergroupNamespaceSecretSpec{
AtomicSpec: &secretclustermodel.VmwareTanzuManageV1alpha1ClusterNamespaceSecretSpec{
SecretType: secretclustermodel.NewVmwareTanzuManageV1alpha1ClusterNamespaceSecretType(secretclustermodel.VmwareTanzuManageV1alpha1ClusterNamespaceSecretTypeSECRETTYPEOPAQUE),
Data: map[string]strfmt.Base64{
"username": []byte(`myuser`),
"password": []byte(`somelongpassword`),
},
},
},
expected: []interface{}{
map[string]interface{}{
OpaqueKey: map[string]interface{}{
"username": "myuser",
"password": "somelongpassword",
},
},
},
},
}

for _, each := range cases {
test := each
t.Run(test.description, func(t *testing.T) {
actual := FlattenSpecForClusterGroupScope(test.input, "somepassword")
actual := FlattenSpecForClusterGroupScope(test.input, "somepassword", map[string]interface{}{"username": "myuser", "password": "somelongpassword"})
require.Equal(t, test.expected, actual)
})
}
Expand Down

0 comments on commit 9ca126c

Please sign in to comment.