Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parameter set controller #101

Merged
merged 7 commits into from
Jun 3, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,12 @@ resources:
kind: CredentialSet
path: get.porter.sh/operator/api/v1
version: v1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: porter.sh
kind: ParameterSet
path: get.porter.sh/operator/api/v1
version: v1
version: "3"
114 changes: 114 additions & 0 deletions api/v1/parameterset_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package v1

import (
"github.com/pkg/errors"
"gopkg.in/yaml.v3"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// SERIALIZATION NOTE:
// * json tags are required for Kubernetes. Any new fields you add must have json tags for the fields to be serialized.
// * yaml tags are required for Porter. Any new fields you add must have yaml tags for the fields to be serialized.

// Parameter defines an element in a ParameterSet
type Parameter struct {
// Name is the bundle parameter name
Name string `json:"name" yaml:"name"`

//Source is the bundle parameter source
//supported: secret, value
//unsupported: file path(via configMap), env var, shell cmd
Source ParameterSource `json:"source" yaml:"source"`
}

type ParameterSource struct {
// Secret is a parameter source using a secret plugin
Secret string `json:"secret,omitempty" yaml:"secret,omitempty"`
// Value is a paremeter source using plaintext value
Value string `json:"value,omitempty" yaml:"value,omitempty"`
}

// ParameterSetSpec defines the desired state of ParameterSet
type ParameterSetSpec struct {
// AgentConfig is the name of an AgentConfig to use instead of the AgentConfig defined at the namespace or system level.
// +optional
AgentConfig *corev1.LocalObjectReference `json:"agentConfig,omitempty" yaml:"-"`

// PorterConfig is the name of a PorterConfig to use instead of the PorterConfig defined at the namespace or system level.
PorterConfig *corev1.LocalObjectReference `json:"porterConfig,omitempty" yaml:"-"`
//
// These are fields from the Porter parameter set resource.
// Your goal is that someone can copy/paste a resource from Porter into the
// spec and have it work. So be consistent!
//

// SchemaVersion is the version of the parameter set state schema.
SchemaVersion string `json:"schemaVersion" yaml:"schemaVersion"`

// Name is the name of the parameter set in Porter. Immutable.
Name string `json:"name" yaml:"name"`

// Namespace (in Porter) where the parameter set is defined.
Namespace string `json:"namespace" yaml:"namespace"`
// Parameters list of bundle parameters in the parameter set.
Parameters []Parameter `json:"parameters" yaml:"parameters"`
}

func (ps ParameterSetSpec) ToPorterDocument() ([]byte, error) {
b, err := yaml.Marshal(ps)
return b, errors.Wrap(err, "error converting the ParameterSet spec into its Porter resource representation")
}

// ParameterSetStatus defines the observed state of ParameterSet
type ParameterSetStatus struct {
PorterResourceStatus `json:",inline"`
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status

// ParameterSet is the Schema for the parametersets API
type ParameterSet struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec ParameterSetSpec `json:"spec,omitempty"`
Status ParameterSetStatus `json:"status,omitempty"`
}

func (ps *ParameterSet) GetStatus() PorterResourceStatus {
return ps.Status.PorterResourceStatus
}

func (ps *ParameterSet) SetStatus(value PorterResourceStatus) {
ps.Status.PorterResourceStatus = value
}

// GetRetryLabelValue returns a value that is safe to use
// as a label value and represents the retry annotation used
// to trigger reconciliation.
func (ps *ParameterSet) GetRetryLabelValue() string {
return getRetryLabelValue(ps.Annotations)
}

// SetRetryAnnotation flags the resource to retry its last operation.
func (ps *ParameterSet) SetRetryAnnotation(retry string) {
if ps.Annotations == nil {
ps.Annotations = make(map[string]string, 1)
}
ps.Annotations[AnnotationRetry] = retry
}

//+kubebuilder:object:root=true

// ParameterSetList contains a list of ParameterSet
type ParameterSetList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ParameterSet `json:"items"`
}

func init() {
SchemeBuilder.Register(&ParameterSet{}, &ParameterSetList{})
}
110 changes: 110 additions & 0 deletions api/v1/parameterset_types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package v1

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

portertest "get.porter.sh/porter/pkg/test"
portertests "get.porter.sh/porter/tests"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestParameterSetSpec_ToPorterDocument(t *testing.T) {
wantGoldenFile := "testdata/parameter-set.yaml"
type fields struct {
AgentConfig *corev1.LocalObjectReference
PorterConfig *corev1.LocalObjectReference
SchemaVersion string
Name string
Namespace string
Parameters []Parameter
}
tests := []struct {
name string
fields fields
wantFile string
wantErrMsg string
}{
{
name: "golden file test",
fields: fields{SchemaVersion: "1.0.1",
Name: "porter-test-me",
Namespace: "dev",
Parameters: []Parameter{
{
Name: "param1",
Source: ParameterSource{Value: "test-param"},
},
{
Name: "param2",
Source: ParameterSource{Secret: "test-secret"},
},
},
},
wantFile: wantGoldenFile,
wantErrMsg: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cs := ParameterSetSpec{
AgentConfig: tt.fields.AgentConfig,
PorterConfig: tt.fields.PorterConfig,
SchemaVersion: tt.fields.SchemaVersion,
Name: tt.fields.Name,
Namespace: tt.fields.Namespace,
Parameters: tt.fields.Parameters,
}
got, err := cs.ToPorterDocument()
if tt.wantErrMsg == "" {
require.NoError(t, err)
portertest.CompareGoldenFile(t, tt.wantFile, string(got))
} else {
portertests.RequireErrorContains(t, err, tt.wantErrMsg)
}
})
}
}

func TestParameterSet_SetRetryAnnotation(t *testing.T) {
type fields struct {
TypeMeta metav1.TypeMeta
ObjectMeta metav1.ObjectMeta
Spec ParameterSetSpec
Status ParameterSetStatus
}
type args struct {
retry string
}
tests := []struct {
name string
fields fields
args args
}{
{
name: "set retry 1",
fields: fields{
TypeMeta: metav1.TypeMeta{},
ObjectMeta: metav1.ObjectMeta{},
Spec: ParameterSetSpec{},
Status: ParameterSetStatus{},
},
args: args{retry: "1"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ps := &ParameterSet{
TypeMeta: tt.fields.TypeMeta,
ObjectMeta: tt.fields.ObjectMeta,
Spec: tt.fields.Spec,
Status: tt.fields.Status,
}
ps.SetRetryAnnotation(tt.args.retry)
assert.Equal(t, tt.args.retry, ps.Annotations[AnnotationRetry])
})
}
}
10 changes: 10 additions & 0 deletions api/v1/testdata/parameter-set.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
schemaVersion: 1.0.1
name: porter-test-me
namespace: dev
parameters:
- name: param1
source:
value: test-param
- name: param2
source:
secret: test-secret
136 changes: 136 additions & 0 deletions api/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading