Skip to content

Commit

Permalink
Fix serialization of service variable when encrypted text is used (#114)
Browse files Browse the repository at this point in the history
* Fix serialization of service variable when encrypted text is used

* Fix application test
  • Loading branch information
micahlmartin authored May 10, 2022
1 parent de7525d commit 91a0d0d
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 70 deletions.
2 changes: 1 addition & 1 deletion harness/cd/application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func TestUpdateApplication(t *testing.T) {

// Setup
name := fmt.Sprintf("%s-%s", t.Name(), utils.RandStringBytes(5))
expectedName := "test_name_change"
expectedName := fmt.Sprintf("%s_test_name_change", name)

// Create a new app
newApp, err := createApplication(name)
Expand Down
48 changes: 48 additions & 0 deletions harness/cd/cac/model_secret_ref.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package cac

import (
"errors"
"fmt"
"strings"
)

type SecretRef struct {
Name string
}

func (r *SecretRef) MarshalYAML() (interface{}, error) {
if (r == &SecretRef{}) {
return []byte{}, nil
}

if r.Name == "" {
return nil, errors.New("name must be set")
}

return fmt.Sprintf("secretName:%s", r.Name), nil
}

func (r *SecretRef) UnmarshalYAML(unmarshal func(interface{}) error) error {

var val interface{}
err := unmarshal(&val)
if err != nil {
return err
}

value := val.(string)

parts := strings.Split(value, ":")

if len(parts) == 1 {
r.Name = parts[0]
} else if len(parts) == 2 {
r.Name = parts[1]
}

return nil
}

func (r *SecretRef) String() string {
return fmt.Sprintf("secretName:%s", r.Name)
}
30 changes: 30 additions & 0 deletions harness/cd/cac/model_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package cac

import (
"reflect"

"github.com/harness/harness-go-sdk/harness/utils"
)

type Service struct {
HarnessApiVersion HarnessApiVersion `yaml:"harnessApiVersion" json:"harnessApiVersion"`
Type ObjectType `yaml:"type" json:"type"`
Id string `yaml:"-"`
Name string `yaml:"-"`
ArtifactType ArtifactType `yaml:"artifactType,omitempty"`
DeploymentType DeploymentType `yaml:"deploymentType,omitempty"`
Description string `yaml:"description,omitempty"`
Tags map[string]string `yaml:"tags,omitempty"`
HelmVersion HelmVersion `yaml:"helmVersion,omitempty"`
ApplicationId string `yaml:"-"`
DeploymentTypeTemplateUri string `yaml:"deploymentTypeTemplateUri,omitempty"`
ConfigVariables []*ServiceVariable `yaml:"configVariables,omitempty"`
}

func (a *Service) IsEmpty() bool {
return reflect.DeepEqual(a, &Service{})
}

func (s *Service) Validate() (bool, error) {
return utils.RequiredStringFieldsSet(s, []string{"ApplicationId"})
}
57 changes: 57 additions & 0 deletions harness/cd/cac/model_service_variable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package cac

import (
"gopkg.in/yaml.v3"
)

type ServiceVariable struct {
Name string `yaml:"name,omitempty"`
Value string `yaml:"value,omitempty"`
ValueType VariableValueType `yaml:"valueType,omitempty"`
}

// We need to customize the marshaling of this object because of the way the `Value`
// field works. When the ValueType is ENCRYPTED_TEXT the value needs to be secretName:<secretName>.

func (s *ServiceVariable) UnmarshalYAML(unmarshal func(interface{}) error) error {

type Alias ServiceVariable

aux := &struct {
*Alias
}{
Alias: (*Alias)(s),
}

if err := unmarshal(&aux.Alias); err != nil {
return err
}

if s.ValueType == VariableOverrideValueTypes.Text {
s.Value = aux.Value
} else if s.ValueType == VariableOverrideValueTypes.EncryptedText {
ref := &SecretRef{}
if err := yaml.Unmarshal([]byte(aux.Value), ref); err != nil {
return err
}

s.Value = ref.Name
}

return nil
}

func (r *ServiceVariable) MarshalYAML() (interface{}, error) {
var aux ServiceVariable = *r

if r.ValueType == VariableOverrideValueTypes.Text {
aux.Value = r.Value
} else if r.ValueType == VariableOverrideValueTypes.EncryptedText {
ref := &SecretRef{
Name: r.Value,
}
aux.Value = ref.String()
}

return aux, nil
}
33 changes: 0 additions & 33 deletions harness/cd/cac/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,35 +77,6 @@ type ResponseMessage struct {
Message string `json:"message"`
}

type Service struct {
HarnessApiVersion HarnessApiVersion `yaml:"harnessApiVersion" json:"harnessApiVersion"`
Type ObjectType `yaml:"type" json:"type"`
Id string `yaml:"-"`
Name string `yaml:"-"`
ArtifactType ArtifactType `yaml:"artifactType,omitempty"`
DeploymentType DeploymentType `yaml:"deploymentType,omitempty"`
Description string `yaml:"description,omitempty"`
Tags map[string]string `yaml:"tags,omitempty"`
HelmVersion HelmVersion `yaml:"helmVersion,omitempty"`
ApplicationId string `yaml:"-"`
DeploymentTypeTemplateUri string `yaml:"deploymentTypeTemplateUri,omitempty"`
ConfigVariables []*ServiceVariable `yaml:"configVariables,omitempty"`
}

func (a *Service) IsEmpty() bool {
return reflect.DeepEqual(a, &Service{})
}

func (s *Service) Validate() (bool, error) {
return utils.RequiredStringFieldsSet(s, []string{"ApplicationId"})
}

type ServiceVariable struct {
Name string `yaml:"name,omitempty"`
Value string `yaml:"value,omitempty"`
ValueType VariableValueType `yaml:"valueType,omitempty"`
}

type AwsCloudProvider struct {
HarnessApiVersion HarnessApiVersion `yaml:"harnessApiVersion" json:"harnessApiVersion"`
Type ObjectType `yaml:"type" json:"type"`
Expand Down Expand Up @@ -273,10 +244,6 @@ type EnvFilter struct {
EntityNames []string `yaml:"entityNames,omitempty"`
}

type SecretRef struct {
Name string
}

type YamlPath string

func (y YamlPath) String() string {
Expand Down
34 changes: 0 additions & 34 deletions harness/cd/cac/utils.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package cac

import (
"errors"
"fmt"
"path"
"reflect"
Expand Down Expand Up @@ -96,39 +95,6 @@ var objectTypeMap = map[ObjectType]reflect.Type{
ObjectTypes.SpotInstCloudProvider: reflect.TypeOf(SpotInstCloudProvider{}),
}

func (r *SecretRef) MarshalYAML() (interface{}, error) {
if (r == &SecretRef{}) {
return []byte{}, nil
}

if r.Name == "" {
return nil, errors.New("name must be set")
}

return fmt.Sprintf("secretName:%s", r.Name), nil
}

func (r *SecretRef) UnmarshalYAML(unmarshal func(interface{}) error) error {

var val interface{}
err := unmarshal(&val)
if err != nil {
return err
}

value := val.(string)

parts := strings.Split(value, ":")

if len(parts) == 1 {
r.Name = parts[0]
} else if len(parts) == 2 {
r.Name = parts[1]
}

return nil
}

func GetEntityNameFromPath(yamlPath YamlPath) string {
dir, file := path.Split(string(yamlPath))

Expand Down
45 changes: 45 additions & 0 deletions harness/cd/cac_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,51 @@ func TestCreateService(t *testing.T) {
require.Equal(t, app.Id, newService.ApplicationId)
}

func TestCreateServiceWithVariables(t *testing.T) {
// Setup
c := getClient()
name := fmt.Sprintf("%s-%s", t.Name(), utils.RandStringBytes(5))
app, err := createApplication(name)
require.NoError(t, err)
require.NotNil(t, app)

// Cleanup
defer func() {
err = c.ApplicationClient.DeleteApplication(app.Id)
require.Nil(t, err, "Failed to delete application: %s", err)
}()

secret, err := createEncryptedTextSecret(name, "secret_value")
require.NoError(t, err)

// Verify
svc, _ := cac.NewEntity(cac.ObjectTypes.Service).(*cac.Service)
svc.Name = name
svc.ApplicationId = app.Id
svc.DeploymentType = cac.DeploymentTypes.Kubernetes
svc.ArtifactType = cac.ArtifactTypes.Docker
svc.ConfigVariables = []*cac.ServiceVariable{
{
Name: "var1",
Value: "value1",
ValueType: cac.VariableOverrideValueTypes.Text,
},
{
Name: "secret",
Value: secret.Name,
ValueType: cac.VariableOverrideValueTypes.EncryptedText,
},
}

newService := &cac.Service{}
err = c.ConfigAsCodeClient.UpsertObject(svc, cac.GetServiceYamlPath(app.Name, name), newService)
require.NoError(t, err)
require.NotEmpty(t, newService.Id)
require.Equal(t, len(svc.ConfigVariables), len(newService.ConfigVariables))
require.Equal(t, app.Id, newService.ApplicationId)

}

func TestGetService(t *testing.T) {
name := fmt.Sprintf("%s_%s", t.Name(), utils.RandStringBytes(4))
// Create application
Expand Down
3 changes: 1 addition & 2 deletions harness/cd/kubernetes_cloudprovider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func TestUpdateKubernetesCloudProvider(t *testing.T) {
Name: updatedName,
ClusterDetailsType: graphql.ClusterDetailsTypes.InheritClusterDetails,
InheritClusterDetails: &graphql.InheritClusterDetails{
DelegateSelectors: []string{"Primary"},
DelegateSelectors: []string{"k8s"},
},
SkipValidation: true,
}
Expand All @@ -75,7 +75,6 @@ func TestUpdateKubernetesCloudProvider(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, updatedCP)
require.Equal(t, updatedName, updatedCP.Name)

err = c.CloudProviderClient.DeleteCloudProvider(cp.Id)
require.NoError(t, err)
}
Expand Down

0 comments on commit 91a0d0d

Please sign in to comment.