Skip to content
package parameters_test
import (
"context"
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest"
)
func TestParameters(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Parameters Suite")
}
var t *envtest.Environment
var cfg *rest.Config
var c client.Client
var ctx context.Context
var _ = BeforeSuite(func() {
var err error
t = &envtest.Environment{
// CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")},
}
cfg, err = t.Start()
Expect(err).NotTo(HaveOccurred())
c, err = client.New(cfg, client.Options{})
Expect(err).NotTo(HaveOccurred())
})
var _ = AfterSuite(func() {
Expect(t.Stop()).To(Succeed())
})
......@@ -53,21 +53,6 @@ var _ = Describe("Parameters", func() {
MountType: MountLiteral,
}
valueFrom = ValueFrom{
FromKey: "FROM_KEY_CONFIG_PARAMETER",
Ref: "configRef",
}
valueFromSecret = ValueFrom{
FromKey: "FROM_KEY_SECRET_PARAMETER",
Ref: "secretRef",
}
valueFromObject = ValueFrom{
FromKey: "status.podIP",
Ref: "v1",
}
paramEnvVarFrom = Parameter{
Key: "VALUE_FROM_CONFIG_PARAMETER",
ValueFrom: valueFrom,
......@@ -75,6 +60,12 @@ var _ = Describe("Parameters", func() {
MountType: MountFrom,
}
valueFrom = ValueFrom{
FromKey: "FROM_KEY_CONFIG_PARAMETER",
Ref: "configRef",
RefType: "configmap",
}
paramEnvVarFromSecret = Parameter{
Key: "VALUE_FROM_SECRET_PARAMETER",
ValueFrom: valueFromSecret,
......@@ -82,6 +73,12 @@ var _ = Describe("Parameters", func() {
MountType: MountFrom,
}
valueFromSecret = ValueFrom{
FromKey: "FROM_KEY_SECRET_PARAMETER",
Ref: "secretRef",
RefType: "secret",
}
paramEnvVarFromObject = Parameter{
Key: "PARAMETER_FROM_OBJECT",
Type: ObjectFieldParameter,
......@@ -89,6 +86,11 @@ var _ = Describe("Parameters", func() {
MountType: MountFrom,
}
valueFromObject = ValueFrom{
FromKey: "status.podIP",
Ref: "v1",
}
paramMountFile = Parameter{
Key: "nginx.conf",
Type: ConfigParameter,
......@@ -104,8 +106,6 @@ var _ = Describe("Parameters", func() {
&paramEnvVar,
&paramEnvVarFrom,
&paramEnvVarFromSecret,
// &paramEnvFrom,
// &paramEnvFromSecret,
&paramEnvVarFromObject,
&paramTemplateLiteral,
&paramTemplateFrom,
......@@ -129,102 +129,6 @@ var _ = Describe("Parameters", func() {
})
Describe("Generating Envirnonment Variables for containers from parameter", func() {
Context("MountType is Literal", func() {
It("should generate envVar", func() {
expectedObj := corev1.EnvVar{
Name: "LITERAL_PARAMETER",
Value: "LiteralParameter",
}
res, err := paramEnvVar.GetEnvVar()
Expect(res).To(Equal(expectedObj))
Expect(err).NotTo(HaveOccurred())
})
})
Context("MountType is From", func() {
It("should generate envVar with valueFrom", func() {
expectedObj := corev1.EnvVar{
Name: "VALUE_FROM_CONFIG_PARAMETER",
ValueFrom: &corev1.EnvVarSource{
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: "configRef",
},
Key: "FROM_KEY_CONFIG_PARAMETER",
},
},
}
// TODO ADD SECRET
res, err := paramEnvVarFrom.GetEnvVar()
Expect(res).To(Equal(expectedObj))
Expect(err).NotTo(HaveOccurred())
})
})
Context("MountType is ObjectField", func() {
It("should generate envVar with valueFrom", func() {
expectedObj := corev1.EnvVar{
Name: "PARAMETER_FROM_OBJECT",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "status.podIP",
},
},
}
res, err := paramEnvVarFromObject.GetEnvVar()
Expect(res).To(Equal(expectedObj))
Expect(err).NotTo(HaveOccurred())
})
})
})
/* Describe("Generating Env for containers with EnvFrom", func() {
Context("Generating env", func() {
It("should generate envFrom", func() {
expectedObj := []corev1.EnvFromSource{
{
ConfigMapRef: &corev1.ConfigMapEnvSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: "myconfigmap",
},
},
},
{
SecretRef: &corev1.SecretEnvSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: "mysecret",
},
},
},
{
SecretRef: &corev1.SecretEnvSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: "myothersecret",
},
},
},
}
res := settings.GetEnvFrom()
Expect(res).To(Equal(expectedObj))
// Expect(err).NotTo(HaveOccurred())
})
})
}) */
Describe("Generating Env for containers with Parameters", func() {
Context("Generating envFrom", func() {
It("should generate envVar", func() {
......@@ -271,7 +175,7 @@ var _ = Describe("Parameters", func() {
},
}
parameters.InitValues()
// parameters.InitValues()
res := parameters.GetEnvVar()
Expect(res).To(Equal(expectedObj))
......@@ -280,10 +184,10 @@ var _ = Describe("Parameters", func() {
})
})
Describe("Generating data for configmap and secret with Parameters", func() {
/* Describe("Generating data for configmap and secret with Parameters", func() {
Context("Generating data", func() {
It("should generate data", func() {
parameters.InitValues()
// parameters.InitValues()
expectedObj := map[string]string{
"TEMPLATE_PARAMETER_FROM": "LiteralParameter",
......@@ -293,38 +197,6 @@ var _ = Describe("Parameters", func() {
// Expect(err).NotTo(HaveOccurred())
})
})
})
/*
Describe("Generating mount files", func() {
Context("Generating volumes & volume mount", func() {
It("should generate volume for pod", func() {
expectedObj := corev1.Volume{
Name: "nginx-conf",
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: "",
},
},
},
}
Expect(paramMountFile.GetPodVolume()).To(Equal(expectedObj))
// Expect(err).NotTo(HaveOccurred())
})
It("should generate volumeMount for container", func() {
expectedObj := corev1.VolumeMount{
Name: "nginx-conf",
ReadOnly: true,
MountPath: "",
SubPath: "",
}
Expect(paramMountFile.GetVolumeMount()).To(Equal(expectedObj))
// Expect(err).NotTo(HaveOccurred())
})
})
})
*/
}) */
})
......@@ -19,15 +19,17 @@ import (
"context"
"errors"
"reflect"
"strings"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.libre.sh/interfaces"
"sigs.k8s.io/controller-runtime/pkg/client"
)
func Marshal(i interface{}) (Parameters, error) {
parameters := Parameters{}
func Marshal(i interface{}) (*Parameters, error) {
parameters := &Parameters{}
t := reflect.TypeOf(i)
......@@ -38,47 +40,40 @@ func Marshal(i interface{}) (Parameters, error) {
fv := ifv.Field(ii)
parameter, ok := fv.Interface().(Parameter)
// TODO Return error
parameter, ok := fv.Interface().(*Parameter)
if !ok {
// return nil, ok
return parameters, errors.New("not parameters type")
}
env, ok := f.Tag.Lookup("env")
if !ok {
// return nil, ok
return parameters, errors.New("missing env tag")
}
if parameter == nil {
parameter = &Parameter{}
}
if len(parameter.Key) == 0 {
parameter.Key = env
}
// if len(parameter.MountType) == 0 {
// parameter.MountType = MountEnvFile
// }
parameters = append(parameters, &parameter)
*parameters = append(*parameters, parameter)
}
return parameters, nil
}
// Sort parameters by keys
func ParametersByKey(p *Parameters) map[string]*Parameter {
// ByKey returns the parameters sorted by keys
func ByKey(p *Parameters) map[string]*Parameter {
paramsByKey := map[string]*Parameter{}
for _, param := range *p {
/* if len(param.FromKey) > 0 {
paramsByKey[param.FromKey] = param
} else { */
paramsByKey[param.Key] = param
// }
}
return paramsByKey
}
// Transform parameters to key:value
// KeyPairValues returns the parameters as key:value pairs
func KeyPairValues(p *Parameters) map[string]string {
data := make(map[string]string)
......@@ -89,61 +84,76 @@ func KeyPairValues(p *Parameters) map[string]string {
return data
}
func InitParametersFromResources() {
// OrderByResourceRef returns a list of parameters ordered reference type and reference name
func OrderByResourceRef(ps *Parameters) map[ParameterType]map[string]*Parameters {
sorted := make(map[ParameterType]map[string]*Parameters)
for _, p := range *ps {
if p != nil {
// TOFIX only refType ? by default secret ?
if len(p.ValueFrom.Ref) > 0 {
// TO DO TO FIX
if len(p.RefType) == 0 {
p.RefType = SecretParameter
}
if len(sorted[p.RefType]) == 0 {
sorted[p.RefType] = make(map[string]*Parameters)
}
if sorted[p.RefType][p.ValueFrom.Ref] == nil {
sorted[p.RefType][p.ValueFrom.Ref] = &Parameters{}
}
*sorted[p.RefType][p.ValueFrom.Ref] = append(*sorted[p.RefType][p.ValueFrom.Ref], p)
}
}
}
return sorted
}
// TODO SPLIT IN GETPARAMETERSFROMSOURCES AND MERGEPARAMETERSBYKEYS
func GetAndMergeParameters(
params Parameters,
paramsByKey map[string]*Parameter,
c client.Client,
obj interfaces.Object) error {
var pType ParameterType
data := map[string]string{}
// GetDataFromResource return the data as key:value pairs from external resources.
// If resources are owned by the owner object, only generated resources are returned.
// Only secrets and configmaps are supported.
func GetDataFromResource(c client.Client, obj, owner interfaces.Object) (data map[string]string, err error) {
objectKey, _ := client.ObjectKeyFromObject(obj)
objData := make(map[string]string)
data = make(map[string]string)
err := c.Get(context.Background(), objectKey, obj)
objectKey, err := client.ObjectKeyFromObject(obj)
if err != nil {
return data, err
}
err = c.Get(context.Background(), objectKey, obj)
if err != nil {
return err
return data, err
}
switch obj.GetObjectKind().GroupVersionKind().Kind {
case "Secret":
pType = SecretParameter
for k, v := range obj.(*corev1.Secret).Data {
data[k] = string(v)
}
case "ConfigMap":
pType = ConfigParameter
for k, v := range obj.(*corev1.ConfigMap).Data {
data[k] = v
switch ro := obj.(type) {
case *corev1.Secret:
for k, v := range ro.Data {
objData[k] = string(v)
}
case *corev1.ConfigMap:
objData = ro.Data
default:
return errors.New("object kind should be ConfigMap or Secret")
return data, errors.New("object kind should be ConfigMap or Secret")
}
if len(params) > 0 {
for _, pp := range params {
paramsByKey[pp.Key].Value = string(data[pp.FromKey])
paramsByKey[pp.Key].Generate = ""
}
} else {
for kk, vv := range data {
if paramsByKey[kk] == nil {
paramsByKey[kk] = &Parameter{}
// If object is owner we only want to get the generated data in order to not regenerate it,
// other parameters are set in crds or valueFrom
if metav1.IsControlledBy(obj, owner) {
if len(obj.GetAnnotations()["settings.k8s.libre.sh/generate"]) > 0 {
for _, param := range strings.Split(obj.GetAnnotations()["settings.k8s.libre.sh/generate"], ",") {
data[param] = objData[param]
}
paramsByKey[kk].Value = vv
paramsByKey[kk].Key = kk
// paramsByKey[kk].MountType = MountEnvFile
// TODO TO FIX This should be checked
paramsByKey[kk].Type = pType
return data, nil
}
} else {
data = objData
}
return nil
return data, nil
}
package parameters_test
import (
"context"
"fmt"
"math/rand"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "k8s.libre.sh/application/settings/parameters"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
var _ = Describe("Utils", func() {
Describe("Merge Parameters", func() {
It("should merge two parameters into a new parameters struct", func() {
srcParam := &Parameter{
Key: "PARAM",
Value: "src_param",
}
extraSrcParam := &Parameter{
Key: "EXTRA_SRC_PARAM",
Value: "extra_src_param",
}
destParam := &Parameter{
Key: "PARAM",
Value: "dest_param",
}
extraDestParam := &Parameter{
Key: "EXTRA_DEST_PARAM",
Value: "extra_dest_param",
}
srcParameters := &Parameters{
srcParam,
extraSrcParam,
}
destParameters := &Parameters{
destParam,
extraDestParam,
}
expectedObj := &Parameters{
// srcParam,
extraSrcParam,
srcParam,
extraDestParam,
}
// res := MergeParameters(srcParameters, destParameters)
err := destParameters.Merge(srcParameters)
expectedObjByKey := ByKey(expectedObj)
// resByKey := ByKey(res)
resByKey := ByKey(destParameters)
Expect(resByKey).To(Equal(expectedObjByKey))
Expect(err).NotTo(HaveOccurred())
})
It("should merge parameters with data", func() {
data := map[string]string{
"FROM_PARAM": "data_param",
"EXTRA_DATA_PARAM": "extra_data_param",
}
dataParam1 := &Parameter{
Key: "FROM_PARAM",
Value: "data_param",
}
dataParam2 := &Parameter{
Key: "EXTRA_DATA_PARAM",
Value: "extra_data_param",
}
destParam := &Parameter{
Key: "PARAM",
ValueFrom: ValueFrom{
FromKey: "FROM_PARAM",
},
Value: "dest_param",
}
// TODO Error if parameter is not in data
// TODO defautl FromKey to Key
extraDestParam1 := &Parameter{
Key: "EXTRA_DEST_PARAM",
Value: "extra_dest_param",
ValueFrom: ValueFrom{
FromKey: "FROM_EXTRA_PARAM",
},
}
destParameters := Parameters{
destParam,
extraDestParam1,
}
expectedParam := &Parameter{
Key: "PARAM",
Value: "data_param",
ValueFrom: destParam.ValueFrom,
}
// res, err := MergeParametersWithData(destParameters, data)
err := destParameters.MergeData(data)
By("returning error when parameter is not in data")
Expect(err).To(HaveOccurred())
By("merging parameters and data when some parameters are set")
expectedObject := &Parameters{
expectedParam,
}
newDestParameters := Parameters{
destParam,
}
// res, err = MergeParametersWithData(newDestParameters, data)
err = newDestParameters.MergeData(data)
Expect(err).NotTo(HaveOccurred())
// Expect(&res).To(Equal(expectedObject))
Expect(newDestParameters).To(Equal(newDestParameters))
By("returning parameters from data when parameters are empty")
expectedObject = &Parameters{
dataParam1,
dataParam2,
}
emptyParams := &Parameters{}
// res, err = MergeParametersWithData(emptyParams, data)
err = emptyParams.MergeData(data)
Expect(err).NotTo(HaveOccurred())
Expect(emptyParams).To(Equal(expectedObject))
})
})
Describe("Get Data From Resource", func() {
It("should get data from resources", func() {
secretName := fmt.Sprintf("secret-%d", rand.Int31())
configName := fmt.Sprintf("config-%d", rand.Int31())
sec := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
Namespace: "default",
},
Data: map[string][]byte{
"Bar": []byte("bar"),
},
}
cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: configName,
Namespace: "default",
},
Data: map[string]string{
"Foo": "foo",
},
}
err := c.Create(context.TODO(), sec)
Expect(err).NotTo(HaveOccurred())
err = c.Create(context.TODO(), cm)
Expect(err).NotTo(HaveOccurred())
owner := &corev1.Pod{}
expectedCmData := map[string]string{
"Foo": "foo",
}
expectedSecretData := map[string]string{
"Bar": "bar",
}
obj := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: configName,
Namespace: "default",
},
}
res, err := GetDataFromResource(c, obj, owner)
Expect(err).NotTo(HaveOccurred())
Expect(res).To(Equal(expectedCmData))
res, err = GetDataFromResource(c, sec, owner)
Expect(err).NotTo(HaveOccurred())
Expect(res).To(Equal(expectedSecretData))
})
})
})
......@@ -16,77 +16,170 @@ limitations under the License.
package settings
import (
"sigs.k8s.io/controller-runtime/pkg/client"
"k8s.libre.sh/application/settings/parameters"
"k8s.libre.sh/interfaces"
"k8s.libre.sh/meta"
"k8s.libre.sh/objects"
)
"sigs.k8s.io/controller-runtime/pkg/client"
const (
// Generate settings as env variables in a configMap or Secret
GenEnvFile SettingsGenerate = "envFile"
)
const (
// Generate settings as env variables in a configMap or Secret
SecretSettings SettingsType = "secret"
)
type Settings interface {
GetMeta() meta.Instance
GetSecretMeta() meta.Instance
GetConfigMapMeta() meta.Instance
GetConfig() Config
SetDefaults()
Init(c client.Client) error
type SettingsGenerate string
type SettingsType string
// +kubebuilder:object:generate=true
type Settings struct {
CreateOptions *CreateOptions `json:"createOptions,omitempty"`
*SettingsSpec `json:",inline"`
}
// +kubebuilder:object:generate=true
type CreateOptions struct {
CommonMeta *meta.ObjectMeta `json:"commonMeta,omitempty"`
SecretMeta *meta.ObjectMeta `json:"secretMeta,omitempty"`
ConfigMeta *meta.ObjectMeta `json:"configMeta,omitempty"`
Generate SettingsGenerate `json:"generate,omitempty"`
SettingsType SettingsType `json:"type,omitempty"`
}
func NewSettings(s Settings) *Component {
return &Component{
CommonMeta: s.GetMeta().(*meta.ObjectMeta),
SecretMeta: s.GetSecretMeta().(*meta.ObjectMeta),
ConfigMeta: s.GetConfigMapMeta().(*meta.ObjectMeta),
ConfigSpec: &ConfigSpec{
Sources: s.GetConfig().GetSources(),
Parameters: s.GetConfig().GetParameters(),
// NewSettings returns a Settings struct
func NewSettings(co *CreateOptions, srcs *Sources, ps *parameters.Parameters) *Settings {
return &Settings{
CreateOptions: co,
SettingsSpec: &SettingsSpec{
Sources: srcs,
Parameters: ps,
},
}
}
/* func GetObjects(s Settings) map[int]objects.Object {
func (opts *CreateOptions) Init() {
if opts.CommonMeta == nil {
opts.CommonMeta = &meta.ObjectMeta{}
}
cm := &configmap.ConfigMap{
ObjectMeta: &meta.ObjectMeta{},
if opts.CommonMeta.Labels == nil {
opts.CommonMeta.Labels = make(map[string]string)
}
secret := &secret.Secret{
ObjectMeta: &meta.ObjectMeta{},
if opts.SecretMeta == nil {
opts.SecretMeta = &meta.ObjectMeta{}
}
objs := make(map[int]objects.Object, 2)
if opts.SecretMeta.Labels == nil {
opts.SecretMeta.Labels = make(map[string]string)
}
if opts.ConfigMeta == nil {
opts.ConfigMeta = &meta.ObjectMeta{}
}
if opts.ConfigMeta.Labels == nil {
opts.SecretMeta.Labels = make(map[string]string)
}
}
// GetCreateOptions return the CreateOptions
func (s *Settings) GetCreateOptions() *CreateOptions { return s.CreateOptions }
// GetConfig return the SettingsSpec
func (s *Settings) GetConfig() Config { return s.SettingsSpec }
// GetMeta return the meta.Instance interface
func (s *Settings) GetMeta() meta.Instance { return s.CreateOptions.CommonMeta }
// GetCreateOptions return the CreateOptions
func (s *Settings) GetObjects() map[int]objects.Object { return GetObjects(s) }
meta.SetObjectMeta(s.GetConfigMapMeta(), cm.ObjectMeta)
meta.SetObjectMeta(s.GetSecretMeta(), secret.ObjectMeta)
// SetDefaults sets the defaults from the create options
func (s *Settings) SetDefaults() {
params := s.GetConfig()
srcs := &Sources{}
for _, p := range *params.GetParameters() {
if p.MountType == parameters.MountEnvFile &&
// TO FIX
p.Type == parameters.SecretParameter &&
len(p.Value) > 0 {
secret.Parameters = append(secret.Parameters, p)
secretSrc := Source{
Ref: s.GetCreateOptions().SecretMeta.GetName(),
Type: "secret",
}
configSrc := Source{
Ref: s.GetCreateOptions().ConfigMeta.GetName(),
Type: "configmap",
}
// Reset sources, we do not want to mount orginal resources
if s.GetCreateOptions().Generate == GenEnvFile {
srcs = &Sources{}
}
for _, p := range *s.GetParameters() {
if p.MountType == parameters.MountEnvFile || s.GetCreateOptions().Generate == GenEnvFile {
p.MountType = parameters.MountEnvFile
// add newly created resource ref to sources
if p.Type == parameters.ConfigParameter {
srcs = AppendSourceIfUnique(srcs, configSrc)
} else if p.Type == parameters.SecretParameter || p.Type == "" {
srcs = AppendSourceIfUnique(srcs, secretSrc)
}
// Reset valueFrom, we do not want to mount orginal resources
p.ValueFrom = parameters.ValueFrom{}
}
if p.MountType == parameters.MountEnvFile &&
p.Type == parameters.ConfigParameter &&
len(p.Value) > 0 {
cm.Parameters = append(cm.Parameters, p)
if s.GetCreateOptions().SettingsType == "configmap" {
p.Type = parameters.ConfigParameter
} else if s.GetCreateOptions().SettingsType == "secret" {
p.Type = parameters.SecretParameter
}
if p.MountType == parameters.MountFile && len(p.Ref) == 0 {
if p.Type == parameters.ConfigParameter {
p.Ref = s.GetCreateOptions().ConfigMeta.GetName()
}
if p.Type == parameters.SecretParameter {
p.Ref = s.GetCreateOptions().SecretMeta.GetName()
}
}
}
// TODO IMPROVE
if len(cm.Parameters) > 0 {
objs[0] = cm
srcs.DeepCopyInto(s.GetSources())
}
// Init initialise the settings.
// ObjectMeta are set from commons meta.
// Parameters are initialised from external resources set in ValueFrom and random values are generated.
func (s *Settings) Init(c client.Client, owner interfaces.Object) error {
if s.CreateOptions == nil {
s.CreateOptions = &CreateOptions{}
}
s.CreateOptions.Init()
if len(secret.Parameters) > 0 {
if objs[0] == nil {
objs[0] = secret
meta.SetObjectMeta(s.CreateOptions.CommonMeta, s.CreateOptions.ConfigMeta)
meta.SetObjectMeta(s.CreateOptions.CommonMeta, s.CreateOptions.SecretMeta)
} else {
objs[1] = secret
}
err := InitParametersValueFrom(s, c, owner)
if err != nil {
return err
}
return objs
s.InitRandValues()
if err != nil {
return err
}
return nil
}
*/
package settings_test
import (
"path/filepath"
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest"
)
func TestSettings(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Settings Suite")
}
var t *envtest.Environment
var cfg *rest.Config
var c client.Client
var _ = BeforeSuite(func() {
var err error
t = &envtest.Environment{
CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")},
}
cfg, err = t.Start()
Expect(err).NotTo(HaveOccurred())
c, err = client.New(cfg, client.Options{})
Expect(err).NotTo(HaveOccurred())
})
var _ = AfterSuite(func() {
Expect(t.Stop()).To(Succeed())
})
package settings_test
import (
"context"
"fmt"
"math/rand"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
. "k8s.libre.sh/application/settings"
"k8s.libre.sh/application/settings/parameters"
"k8s.libre.sh/meta"
)
var _ = Describe("Settings", func() {
Describe("InitParametersValueFrom", func() {
var sec *corev1.Secret
var cm *corev1.ConfigMap
var secSource /* , cmSource */ Source
var cpt *Settings
var owner *corev1.Pod
var commonMeta, configMeta, secretMeta *meta.ObjectMeta
var parameterFromConfigMap *parameters.Parameter
BeforeEach(func() {
// ns := "default"
secretName := fmt.Sprintf("secret-%d", rand.Int31())
configName := fmt.Sprintf("config-%d", rand.Int31())
sec = &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
Namespace: "default",
},
Data: map[string][]byte{
"Bar": []byte("bar"),
},
}
cm = &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: configName,
Namespace: "default",
},
Data: map[string]string{
"Foo": "foo",
},
}
secSource = Source{
Ref: secretName,
Type: "secret",
}
/* cmSource = Source{
Ref: configName,
Type: "configmap",
} */
commonMeta = &meta.ObjectMeta{
Name: "test",
Namespace: "default",
}
commonMeta.Labels = make(map[string]string)
commonMeta.SetInstance("test")
commonMeta.SetApplication("test")
commonMeta.SetComponent("test")
secretMeta = &meta.ObjectMeta{
Name: "test",
}
configMeta = &meta.ObjectMeta{
Name: "test",
}
parameterFromConfigMap = &parameters.Parameter{
Key: "FooFoo",
Type: "configmap",
ValueFrom: parameters.ValueFrom{
Ref: configName,
FromKey: "Foo",
RefType: "configmap",
},
}
/* parameterFromSecret = &parameters.Parameter{
Key: "FooFoo",
Type: "configmap",
ValueFrom: parameters.ValueFrom{
Ref: configName,
FromKey: "Foo",
RefType: "configmap",
},
} */
cpt = &Settings{
CreateOptions: &CreateOptions{
CommonMeta: commonMeta,
SecretMeta: secretMeta,
ConfigMeta: configMeta,
// Generate: GenEnvFile,
SettingsType: "",
},
SettingsSpec: &SettingsSpec{
Sources: &Sources{
secSource,
// cmSource,
},
Parameters: &parameters.Parameters{
parameterFromConfigMap,
},
},
}
owner = &corev1.Pod{}
owner.SetName("test")
owner.SetNamespace("default")
err := c.Create(context.TODO(), sec)
Expect(err).NotTo(HaveOccurred())
err = c.Create(context.TODO(), cm)
Expect(err).NotTo(HaveOccurred())
})
It("initialize parameters from valueFrom", func() {
parameterFromConfigMap.Value = "foo"
expectedParamFromSourceCm := &parameters.Parameter{
Key: "Bar",
Value: "bar",
}
expectedParams := &parameters.Parameters{
parameterFromConfigMap,
expectedParamFromSourceCm,
}
err := InitParametersValueFrom(cpt, c, owner)
Expect(err).NotTo(HaveOccurred())
Expect(cpt.Parameters).To(Equal(expectedParams))
})
It("initialize parameters from valueFrom with generate envFile", func() {
cpt.CreateOptions.Generate = GenEnvFile
expectedParamFromSourceCm := &parameters.Parameter{
Key: "Bar",
Value: "bar",
MountType: parameters.MountEnvFile,
}
err := InitParametersValueFrom(cpt, c, owner)
parameterFromConfigMap.Value = "foo"
parameterFromConfigMap.MountType = parameters.MountEnvFile
expectedParams := &parameters.Parameters{
parameterFromConfigMap,
expectedParamFromSourceCm,
}
Expect(err).NotTo(HaveOccurred())
Expect(cpt.Parameters).To(Equal(expectedParams))
})
It("initialize parameters from valueFrom with default settings to configmap", func() {
cpt.CreateOptions.Generate = GenEnvFile
cpt.CreateOptions.SettingsType = "configmap"
expectedParamFromSourceCm := &parameters.Parameter{
Key: "Bar",
Value: "bar",
MountType: parameters.MountEnvFile,
Type: parameters.ConfigParameter,
}
err := InitParametersValueFrom(cpt, c, owner)
parameterFromConfigMap.Value = "foo"
parameterFromConfigMap.MountType = parameters.MountEnvFile
parameterFromConfigMap.Type = parameters.ConfigParameter
expectedParams := &parameters.Parameters{
parameterFromConfigMap,
expectedParamFromSourceCm,
}
Expect(err).NotTo(HaveOccurred())
Expect(cpt.Parameters).To(Equal(expectedParams))
})
It("initialize parameters from valueFrom with default settings to secret", func() {
cpt.CreateOptions.Generate = GenEnvFile
cpt.CreateOptions.SettingsType = "secret"
expectedParamFromSourceCm := &parameters.Parameter{
Key: "Bar",
Value: "bar",
MountType: parameters.MountEnvFile,
Type: parameters.SecretParameter,
}
err := InitParametersValueFrom(cpt, c, owner)
parameterFromConfigMap.Value = "foo"
parameterFromConfigMap.MountType = parameters.MountEnvFile
parameterFromConfigMap.Type = parameters.SecretParameter
expectedParams := &parameters.Parameters{
parameterFromConfigMap,
expectedParamFromSourceCm,
}
Expect(err).NotTo(HaveOccurred())
Expect(cpt.Parameters).To(Equal(expectedParams))
})
})
})
......@@ -30,6 +30,7 @@ limitations under the License.
// - can be randomly generate
// - provided in the crd
// - generate by template
// - provided in a resource in the same namespace - only secrets and configmaps are supported
package settings
import (
......@@ -39,6 +40,9 @@ import (
"k8s.libre.sh/application/settings/parameters"
)
// +kubebuilder:object:generate=true
type Sources []Source
// +kubebuilder:object:generate=true
type Source struct {
// Ref is the name of a resource in the same namespace
......@@ -48,61 +52,62 @@ type Source struct {
Type string `json:"type,omitempty"`
}
// ConfigSpec defines a list of parameters and references to resources from which those parameters can be fetched
// SettingsSpec defines a list of parameters and references to resources from which those parameters can be fetched
// Only secrets and configmaps in the same namespace are supported as references
// +kubebuilder:object:generate=true
type ConfigSpec struct {
type SettingsSpec struct {
// Sources is a list of sources for the parameters from kubernetes resources in the same namespace
Sources []Source `json:"sources,omitempty"`
// Sources []Source `json:"sources,omitempty"`
Sources *Sources `json:"sources,omitempty"`
// Parameters is a list of parameters
*parameters.Parameters `json:"parameters,omitempty"`
}
// SetParameters sets the parameters
func (c *ConfigSpec) SetParameters(parameters *parameters.Parameters) { c.Parameters = parameters }
// GetParameters return the parameters
func (c *ConfigSpec) GetParameters() *parameters.Parameters {
func (c *SettingsSpec) GetParameters() *parameters.Parameters {
if c.Parameters == nil {
c.Parameters = &parameters.Parameters{}
}
return c.Parameters
}
func (c *ConfigSpec) GetSources() []Source { return c.Sources }
func (c *ConfigSpec) SetSources(sources []Source) { c.Sources = sources }
// GetSources return the sources
func (c *SettingsSpec) GetSources() *Sources {
if c.Sources == nil {
c.Sources = &Sources{}
}
return c.Sources
}
// GetEnvFrom returns a list of EnvFromSource to populate environment variables in the container.
func (c *ConfigSpec) GetEnvFrom() []corev1.EnvFromSource {
// envFroms := []corev1.EnvFromSource{}
func (c *SettingsSpec) GetEnvFrom() []corev1.EnvFromSource {
envFromSecret := []corev1.EnvFromSource{}
envFromConfigMap := []corev1.EnvFromSource{}
// envFromMap := map[int]corev1.EnvFromSource{}
envFrom := corev1.EnvFromSource{}
src := Source{}
for _, p := range *c.Parameters {
if p.MountType == parameters.MountEnvFile && len(p.Ref) > 0 {
if p.Type == parameters.ConfigParameter {
src = Source{
Ref: p.Ref,
Type: string(p.Type),
}
c.Sources = append(c.Sources, src)
} else if p.Type == parameters.SecretParameter {
src = Source{
Ref: p.Ref,
Type: string(p.Type),
if c.Parameters != nil {
for _, p := range *c.Parameters {
if p.MountType == parameters.MountEnvFile && len(p.Ref) > 0 {
if p.Type == parameters.ConfigParameter {
src := Source{
Ref: p.Ref,
Type: string(p.Type),
}
c.Sources = AppendSourceIfUnique(c.Sources, src)
} else if p.Type == parameters.SecretParameter {
src := Source{
Ref: p.Ref,
Type: string(p.Type),
}
c.Sources = AppendSourceIfUnique(c.Sources, src)
}
c.Sources = append(c.Sources, src)
}
}
}
if len(c.Sources) > 0 {
for _, source := range c.Sources {
if c.Sources != nil {
for _, source := range *c.Sources {
if source.Type == "configmap" {
envFrom = corev1.EnvFromSource{
ConfigMapRef: &corev1.ConfigMapEnvSource{
......@@ -111,7 +116,6 @@ func (c *ConfigSpec) GetEnvFrom() []corev1.EnvFromSource {
},
},
}
// envFromMap[k] = envFrom
envFromConfigMap = append(envFromConfigMap, envFrom)
} else if source.Type == "secret" {
envFrom = corev1.EnvFromSource{
......@@ -121,44 +125,40 @@ func (c *ConfigSpec) GetEnvFrom() []corev1.EnvFromSource {
},
},
}
// envFromMap[k] = envFrom
envFromSecret = append(envFromSecret, envFrom)
}
}
}
// We need to sort so the order is always the same and container is not update
// if len(envFromSecret) > 0 {
// We need to sort so the order is always the same and container is not updated
sort.SliceStable(envFromSecret, func(i, j int) bool {
return envFromSecret[i].SecretRef.Name < envFromSecret[j].SecretRef.Name
})
sort.SliceStable(envFromConfigMap, func(i, j int) bool {
return envFromConfigMap[i].ConfigMapRef.Name < envFromConfigMap[j].ConfigMapRef.Name
})
// }
envFroms := append(envFromSecret, envFromConfigMap...)
/* if len(envFroms) > 0 {
return envFroms
}
*/
/* for _, v := range envFromMap {
envFroms = append(envFroms, v)
}
*/
return envFroms
// return nil
if len(envFroms) > 0 {
return envFroms
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) {
func (in *SettingsSpec) DeepCopyInto(out *SettingsSpec) {
*out = *in
if in.Sources != nil {
in, out := &in.Sources, &out.Sources
*out = make([]Source, len(*in))
copy(*out, *in)
*out = new(Sources)
if **in != nil {
in, out := *in, *out
*out = make([]Source, len(*in))
copy(*out, *in)
}
}
if in.Parameters != nil {
in, out := &in.Parameters, &out.Parameters
......@@ -177,12 +177,12 @@ func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) {
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec.
func (in *ConfigSpec) DeepCopy() *ConfigSpec {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SettingsSpec.
func (in *SettingsSpec) DeepCopy() *SettingsSpec {
if in == nil {
return nil
}
out := new(ConfigSpec)
out := new(SettingsSpec)
in.DeepCopyInto(out)
return out
}
......@@ -15,59 +15,18 @@ limitations under the License.
package settings
import "k8s.libre.sh/application/settings/parameters"
func OrderByResourceRef(s *ConfigSpec) (secrets, configMaps map[string]parameters.Parameters) {
secrets = make(map[string]parameters.Parameters)
configMaps = make(map[string]parameters.Parameters)
for _, source := range s.Sources {
if source.Type == "secret" {
secrets[source.Ref] = parameters.Parameters{}
} else if source.Type == "configmap" {
configMaps[source.Ref] = parameters.Parameters{}
func AppendSourceIfUnique(sources *Sources, source Source) *Sources {
srcs := Sources{}
if sources != nil {
for _, ele := range *sources {
if ele == source {
return sources
}
}
}
// Then we get the sources that are provided for each parameters and will need a transformation
for _, p := range *s.Parameters {
if len(p.ValueFrom.Ref) > 0 && p.Type == parameters.SecretParameter {
secrets[p.ValueFrom.Ref] = append(secrets[p.ValueFrom.Ref], p)
}
if len(p.ValueFrom.Ref) > 0 && p.Type == parameters.ConfigParameter {
configMaps[p.ValueFrom.Ref] = append(configMaps[p.ValueFrom.Ref], p)
}
}
srcs = append(srcs, source)
return secrets, configMaps
return &srcs
}
/*
func OrderBySourceTypeAndRef(s *ConfigSpec) (orderedParams map[string]map[string]parameters.Parameters) {
// We order the parameters by secret and configmap sources
// First we get the sources provided that should be mounted untouched
// paramsByResourceName = make(map[string]parameters.Parameters)
orderedParams = make(map[string]map[string]parameters.Parameters)
orderedParams["secret"] = make(map[string]parameters.Parameters)
orderedParams["configmap"] = make(map[string]parameters.Parameters)
orderedParams["field"] = make(map[string]parameters.Parameters)
orderedParams["templateValue"] = make(map[string]parameters.Parameters)
for _, ref := range s.SecretRefs {
orderedParams["secret"][ref] = parameters.Parameters{}
}
for _, ref := range s.ConfigRefs {
orderedParams["configmap"][ref] = parameters.Parameters{}
}
// Then we get the sources that are provided for each parameters and will need a transformation
for _, p := range *s.Parameters {
if len(p.ValueFrom.Ref) > 0 {
orderedParams[string(p.Type)][p.ValueFrom.Ref] = append(orderedParams[string(p.Type)][p.ValueFrom.Ref], p)
}
}
return orderedParams
}
*/
......@@ -24,7 +24,7 @@ import (
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Component) DeepCopyInto(out *Component) {
func (in *CreateOptions) DeepCopyInto(out *CreateOptions) {
*out = *in
if in.CommonMeta != nil {
in, out := &in.CommonMeta, &out.CommonMeta
......@@ -41,18 +41,38 @@ func (in *Component) DeepCopyInto(out *Component) {
*out = new(meta.ObjectMeta)
(*in).DeepCopyInto(*out)
}
if in.ConfigSpec != nil {
in, out := &in.ConfigSpec, &out.ConfigSpec
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CreateOptions.
func (in *CreateOptions) DeepCopy() *CreateOptions {
if in == nil {
return nil
}
out := new(CreateOptions)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Settings) DeepCopyInto(out *Settings) {
*out = *in
if in.CreateOptions != nil {
in, out := &in.CreateOptions, &out.CreateOptions
*out = new(CreateOptions)
(*in).DeepCopyInto(*out)
}
if in.SettingsSpec != nil {
in, out := &in.SettingsSpec, &out.SettingsSpec
*out = (*in).DeepCopy()
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Component.
func (in *Component) DeepCopy() *Component {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Settings.
func (in *Settings) DeepCopy() *Settings {
if in == nil {
return nil
}
out := new(Component)
out := new(Settings)
in.DeepCopyInto(out)
return out
}
......@@ -71,3 +91,22 @@ func (in *Source) DeepCopy() *Source {
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in Sources) DeepCopyInto(out *Sources) {
{
in := &in
*out = make(Sources, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Sources.
func (in Sources) DeepCopy() Sources {
if in == nil {
return nil
}
out := new(Sources)
in.DeepCopyInto(out)
return *out
}
mode: set
k8s.libre.sh/application/settings/parameters/utils.go:22.49,29.39 4 0
k8s.libre.sh/application/settings/parameters/utils.go:56.2,56.24 1 0
k8s.libre.sh/application/settings/parameters/utils.go:29.39,36.10 4 0
k8s.libre.sh/application/settings/parameters/utils.go:40.3,41.10 2 0
k8s.libre.sh/application/settings/parameters/utils.go:45.3,45.30 1 0
k8s.libre.sh/application/settings/parameters/utils.go:49.3,49.36 1 0
k8s.libre.sh/application/settings/parameters/utils.go:53.3,53.46 1 0
k8s.libre.sh/application/settings/parameters/utils.go:36.11,38.4 0 0
k8s.libre.sh/application/settings/parameters/utils.go:41.11,43.4 0 0
k8s.libre.sh/application/settings/parameters/utils.go:45.30,47.4 1 0
k8s.libre.sh/application/settings/parameters/utils.go:49.36,51.4 1 0
k8s.libre.sh/application/settings/parameters/utils.go:59.59,62.23 2 0
k8s.libre.sh/application/settings/parameters/utils.go:66.2,66.20 1 0
k8s.libre.sh/application/settings/parameters/utils.go:62.23,64.3 1 0
k8s.libre.sh/application/settings/parameters/utils.go:69.53,72.27 2 1
k8s.libre.sh/application/settings/parameters/utils.go:76.2,76.13 1 1
k8s.libre.sh/application/settings/parameters/utils.go:72.27,74.3 1 1
k8s.libre.sh/application/settings/parameters/zz_generated.deepcopy.go:25.51,29.2 3 0
k8s.libre.sh/application/settings/parameters/zz_generated.deepcopy.go:32.44,33.15 1 0
k8s.libre.sh/application/settings/parameters/zz_generated.deepcopy.go:36.2,38.12 3 0
k8s.libre.sh/application/settings/parameters/zz_generated.deepcopy.go:33.15,35.3 1 0
k8s.libre.sh/application/settings/parameters/zz_generated.deepcopy.go:42.52,43.2 1 0
k8s.libre.sh/application/settings/parameters/zz_generated.deepcopy.go:43.2,46.22 3 0
k8s.libre.sh/application/settings/parameters/zz_generated.deepcopy.go:46.22,47.23 1 0
k8s.libre.sh/application/settings/parameters/zz_generated.deepcopy.go:47.23,51.5 3 0
k8s.libre.sh/application/settings/parameters/zz_generated.deepcopy.go:57.44,58.15 1 0
k8s.libre.sh/application/settings/parameters/zz_generated.deepcopy.go:61.2,63.13 3 0
k8s.libre.sh/application/settings/parameters/zz_generated.deepcopy.go:58.15,60.3 1 0
k8s.libre.sh/application/settings/parameters/parameter_helper.go:24.67,26.21 1 1
k8s.libre.sh/application/settings/parameters/parameter_helper.go:28.20,29.41 1 1
k8s.libre.sh/application/settings/parameters/parameter_helper.go:36.3,36.65 1 0
k8s.libre.sh/application/settings/parameters/parameter_helper.go:38.17,39.61 1 1
k8s.libre.sh/application/settings/parameters/parameter_helper.go:82.3,82.49 1 0
k8s.libre.sh/application/settings/parameters/parameter_helper.go:84.10,85.47 1 1
k8s.libre.sh/application/settings/parameters/parameter_helper.go:29.41,35.4 2 1
k8s.libre.sh/application/settings/parameters/parameter_helper.go:39.61,40.18 1 1
k8s.libre.sh/application/settings/parameters/parameter_helper.go:41.25,53.23 2 1
k8s.libre.sh/application/settings/parameters/parameter_helper.go:55.25,67.23 2 1
k8s.libre.sh/application/settings/parameters/parameter_helper.go:69.30,79.23 2 1
k8s.libre.sh/application/settings/parameters/parameter_helper.go:89.51,91.2 1 0
k8s.libre.sh/application/settings/parameters/parameter_helper.go:93.58,95.2 1 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:29.35,32.2 2 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:34.39,35.27 1 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:35.27,37.126 1 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:37.126,39.26 2 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:40.24,43.19 3 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:45.5,45.25 1 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:47.24,50.19 3 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:52.5,52.25 1 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:43.20,44.6 0 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:50.20,51.6 0 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:58.73,60.27 1 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:78.2,78.12 1 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:60.27,61.41 1 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:61.41,64.18 2 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:68.4,71.18 3 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:75.4,75.30 1 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:64.18,66.5 1 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:71.18,73.5 1 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:81.50,84.27 2 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:92.2,92.13 1 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:84.27,87.25 1 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:87.25,89.4 1 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:95.50,101.27 4 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:112.2,112.22 1 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:115.2,115.12 1 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:101.27,104.17 2 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:107.3,107.27 1 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:104.18,105.4 0 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:107.27,109.4 1 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:112.22,114.3 1 1
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:118.128,124.16 3 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:128.2,130.61 2 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:135.2,135.64 1 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:141.2,141.21 1 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:157.2,157.12 1 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:124.16,126.3 1 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:130.61,131.47 1 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:131.47,133.4 1 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:135.64,136.50 1 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:136.50,138.4 1 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:141.21,142.29 1 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:142.29,144.4 1 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:145.8,146.28 1 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:146.28,147.30 1 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:150.4,153.44 3 0
k8s.libre.sh/application/settings/parameters/parameters_helpers.go:147.30,149.5 1 0
......@@ -3,15 +3,24 @@ module k8s.libre.sh
go 1.13
require (
github.com/golangci/golangci-lint v1.27.0 // indirect
github.com/onsi/ginkgo v1.12.0
github.com/onsi/gomega v1.9.0
cloud.google.com/go/logging v1.0.0
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 // indirect
github.com/go-logr/zapr v0.1.1 // indirect
github.com/golangci/golangci-lint v1.26.0 // indirect
github.com/hashicorp/go-version v1.2.1
github.com/onsi/ginkgo v1.12.1
github.com/onsi/gomega v1.10.1
github.com/presslabs/controller-util v0.2.2
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 // indirect
k8s.io/api v0.18.1
k8s.io/apimachinery v0.18.1
k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible
sigs.k8s.io/controller-runtime v0.5.0
github.com/prometheus/client_golang v1.5.1 // indirect
go.uber.org/zap v1.14.1 // indirect
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904 // indirect
golang.org/x/tools v0.0.0-20200502202811-ed308ab3e770 // indirect
google.golang.org/api v0.29.0 // indirect
k8s.io/api v0.18.4
k8s.io/apimachinery v0.18.4
k8s.io/client-go v12.0.0+incompatible
sigs.k8s.io/cli-utils v0.13.0
sigs.k8s.io/controller-runtime v0.6.1
)
replace k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible => k8s.io/client-go v0.17.2
replace k8s.io/client-go => k8s.io/client-go v0.18.2
This diff is collapsed.
......@@ -71,3 +71,44 @@ func SetObjectMeta(src Instance, dest Instance) {
}
}
func SetObjectMetaFromInstance(src Instance, dest Instance) {
if len(dest.GetInstance()) == 0 {
dest.SetInstance(src.GetInstance())
}
if len(dest.GetApplication()) == 0 {
dest.SetApplication(src.GetApplication())
}
if len(dest.GetVersion()) == 0 {
dest.SetVersion(src.GetVersion())
}
if len(dest.GetPartOf()) == 0 {
dest.SetPartOf(src.GetPartOf())
}
if len(dest.GetManagedBy()) == 0 {
dest.SetManagedBy(src.GetManagedBy())
}
if len(dest.GetNamespace()) == 0 {
dest.SetNamespace(src.GetNamespace())
}
}
func MergeObjectMeta(src Instance, dest Instance) {
dest.SetLabels(labels.Merge(dest.GetLabels(), InstanceLabels(src)))
if len(dest.GetName()) == 0 {
dest.SetName(fmt.Sprintf("%v-%v", src.GetInstance(), dest.GetComponent()))
}
if len(dest.GetNamespace()) == 0 {
dest.SetNamespace(src.GetNamespace())
}
}
......@@ -60,11 +60,12 @@ type ObjectMeta struct {
// SetLabels sets the ObjectMeta labels
func (c *ObjectMeta) SetLabels(labels map[string]string) {
if len(c.Labels) == 0 {
c.Labels = make(map[string]string)
}
if len(labels) > 0 {
if len(c.Labels) == 0 {
c.Labels = make(map[string]string, len(labels))
}
for k, v := range labels {
// TODO do we need this ? why == 0 ?
if len(c.Labels[k]) == 0 {
c.Labels[k] = v
}
......@@ -74,10 +75,10 @@ func (c *ObjectMeta) SetLabels(labels map[string]string) {
// SetAnnotations sets the ObjectMeta annotations
func (c *ObjectMeta) SetAnnotations(annotations map[string]string) {
if len(c.Annotations) == 0 {
c.Annotations = make(map[string]string)
}
if len(annotations) > 0 {
if len(c.Annotations) == 0 {
c.Annotations = make(map[string]string, len(annotations))
}
for k, v := range annotations {
if len(c.Annotations[k]) == 0 {
c.Annotations[k] = v
......@@ -108,34 +109,77 @@ func (o *ObjectMeta) SetNamespace(namespace string) { o.Namespace = namespace }
func (c *ObjectMeta) GetApplication() string { return c.Labels["app.kubernetes.io/name"] }
// SetApplication sets the ObjectMeta application name from the app.kubernetes.io/name label
func (c *ObjectMeta) SetApplication(s string) { c.Labels["app.kubernetes.io/name"] = s }
// func (c *ObjectMeta) SetApplication(s string) { c.Labels["app.kubernetes.io/name"] = s }
// SetApplication sets the ObjectMeta application name from the app.kubernetes.io/name label
func (c *ObjectMeta) SetApplication(s string) {
if len(c.Labels) == 0 {
c.Labels = make(map[string]string)
}
c.Labels["app.kubernetes.io/name"] = s
}
// GetInstance returns the ObjectMeta application name from the app.kubernetes.io/instance label
func (c *ObjectMeta) GetInstance() string { return c.Labels["app.kubernetes.io/instance"] }
// SetInstance sets the ObjectMeta application name from the app.kubernetes.io/instance label
func (c *ObjectMeta) SetInstance(s string) { c.Labels["app.kubernetes.io/instance"] = s }
// func (c *ObjectMeta) SetInstance(s string) { c.Labels["app.kubernetes.io/instance"] = s }
func (c *ObjectMeta) SetInstance(s string) {
if len(c.Labels) == 0 {
c.Labels = make(map[string]string)
}
c.Labels["app.kubernetes.io/instance"] = s
}
// GetVersion returns the ObjectMeta application name from the app.kubernetes.io/version label
func (c *ObjectMeta) GetVersion() string { return c.Labels["app.kubernetes.io/version"] }
// SetVersion sets the ObjectMeta application name from the app.kubernetes.io/version label
func (c *ObjectMeta) SetVersion(s string) { c.Labels["app.kubernetes.io/version"] = s }
// func (c *ObjectMeta) SetVersion(s string) { c.Labels["app.kubernetes.io/version"] = s }
func (c *ObjectMeta) SetVersion(s string) {
if len(c.Labels) == 0 {
c.Labels = make(map[string]string)
}
c.Labels["app.kubernetes.io/version"] = s
}
// GetComponent returns the ObjectMeta application name from the app.kubernetes.io/component label
func (c *ObjectMeta) GetComponent() string { return c.Labels["app.kubernetes.io/component"] }
// SetComponent sets the ObjectMeta application name from the app.kubernetes.io/component label
func (c *ObjectMeta) SetComponent(s string) { c.Labels["app.kubernetes.io/component"] = s }
// func (c *ObjectMeta) SetComponent(s string) { c.Labels["app.kubernetes.io/component"] = s }
func (c *ObjectMeta) SetComponent(s string) {
if len(c.Labels) == 0 {
c.Labels = make(map[string]string)
}
c.Labels["app.kubernetes.io/component"] = s
}
// GetPartOf returns the ObjectMeta application name from the app.kubernetes.io/part-of label
func (c *ObjectMeta) GetPartOf() string { return c.Labels["app.kubernetes.io/part-of"] }
// SetPartOf sets the ObjectMeta application name from the app.kubernetes.io/part-of label
func (c *ObjectMeta) SetPartOf(s string) { c.Labels["app.kubernetes.io/part-of"] = s }
// func (c *ObjectMeta) SetPartOf(s string) { c.Labels["app.kubernetes.io/part-of"] = s }
func (c *ObjectMeta) SetPartOf(s string) {
if len(c.Labels) == 0 {
c.Labels = make(map[string]string)
}
c.Labels["app.kubernetes.io/part-of"] = s
}
// GetManagedBy returns the ObjectMeta application name from the app.kubernetes.io/managed-by label
func (c *ObjectMeta) GetManagedBy() string { return c.Labels["app.kubernetes.io/managed-by"] }
// SetManagedBy sets the ObjectMeta application name from the app.kubernetes.io/managed-by label
func (c *ObjectMeta) SetManagedBy(s string) { c.Labels["app.kubernetes.io/managed-by"] = s }
//func (c *ObjectMeta) SetManagedBy(s string) { c.Labels["app.kubernetes.io/managed-by"] = s }
func (c *ObjectMeta) SetManagedBy(s string) {
if len(c.Labels) == 0 {
c.Labels = make(map[string]string)
}
c.Labels["app.kubernetes.io/managed-by"] = s
}
......@@ -21,25 +21,12 @@ import (
)
type Mutate interface {
GetData() map[string]string
GetConfigData() map[string]string
}
func MutateConfigMap(r Mutate, obj *corev1.ConfigMap, m meta.Meta) error {
data := r.GetData()
if len(obj.Data) == 0 {
obj.Data = make(map[string]string, len(data))
}
// TODO TO FIX data won't be removed if parameter removed
/* if len(data) > 0 {
for k, v := range data {
obj.Data[k] = v
}
} */
obj.Data = data
obj.Data = r.GetConfigData()
meta.MutateMeta(m, obj)
......
......@@ -16,6 +16,7 @@ limitations under the License.
package configmap
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
parameters "k8s.libre.sh/application/settings/parameters"
interfaces "k8s.libre.sh/interfaces"
meta "k8s.libre.sh/meta"
......@@ -25,8 +26,20 @@ import (
// +kubebuilder:object:generate=true
type ConfigMap struct {
*meta.ObjectMeta `json:"meta,omitempty"`
parameters.Parameters `json:"parameters,omitempty"`
*meta.ObjectMeta `json:"meta,omitempty"`
Data map[string]string `json:"data,omitempty"`
}
func (obj *ConfigMap) GetConfigData() map[string]string { return obj.Data }
func (obj *ConfigMap) Init() {
if obj.ObjectMeta == nil {
obj.ObjectMeta = &meta.ObjectMeta{}
}
if obj.ObjectMeta.Labels == nil {
obj.ObjectMeta.Labels = make(map[string]string)
}
}
func (o *ConfigMap) SetSettings(parameters parameters.Parameters) {}
......@@ -37,5 +50,18 @@ func (o *ConfigMap) Mutate(obj interfaces.Object) error {
}
func (o *ConfigMap) GetObject() interfaces.Object {
return &corev1.ConfigMap{}
obj := &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
Kind: "ConfigMap",
APIVersion: "v1",
},
}
obj.SetName(o.GetName())
obj.SetNamespace(o.GetNamespace())
return obj
}
func (o *ConfigMap) GetObjectKind() string { return "Configmap" }
func (o *ConfigMap) GetObjectGroup() string { return "core" }
......@@ -20,7 +20,6 @@ limitations under the License.
package configmap
import (
"k8s.libre.sh/application/settings/parameters"
"k8s.libre.sh/meta"
)
......@@ -32,15 +31,11 @@ func (in *ConfigMap) DeepCopyInto(out *ConfigMap) {
*out = new(meta.ObjectMeta)
(*in).DeepCopyInto(*out)
}
if in.Parameters != nil {
in, out := &in.Parameters, &out.Parameters
*out = make(parameters.Parameters, len(*in))
for i := range *in {
if (*in)[i] != nil {
in, out := &(*in)[i], &(*out)[i]
*out = new(parameters.Parameter)
**out = **in
}
if in.Data != nil {
in, out := &in.Data, &out.Data
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
}
......
......@@ -21,7 +21,7 @@ import (
type Mutate interface {
// Parameters
// GetVolumeMount() []corev1.VolumeMount
GetVolumeMounts() []corev1.VolumeMount
GetEnvFrom() []corev1.EnvFromSource
GetEnvVar() []corev1.EnvVar
// Runtime
......@@ -32,6 +32,7 @@ type Mutate interface {
GetContainerLivenessProbe() *corev1.Probe
GetContainerReadinessProbe() *corev1.Probe
GetContainerArgs() []string
GetContainerCommand() []string
}
func MutateContainer(r Mutate, obj *corev1.Container) error {
......@@ -42,11 +43,12 @@ func MutateContainer(r Mutate, obj *corev1.Container) error {
obj.LivenessProbe = r.GetContainerLivenessProbe()
obj.ReadinessProbe = r.GetContainerReadinessProbe()
obj.Args = r.GetContainerArgs()
obj.Command = r.GetContainerCommand()
obj.EnvFrom = r.GetEnvFrom()
obj.Env = r.GetEnvVar()
// obj.VolumeMounts = r.GetVolumeMount()
obj.VolumeMounts = r.GetVolumeMounts()
return nil
}
......@@ -28,8 +28,8 @@ import (
//
// +kubebuilder:object:generate=true
type Container struct {
*ContainerSpec `json:",inline"`
*parameters.ConfigSpec `json:"parameters,omitempty"`
*ContainerSpec `json:",inline"`
*parameters.SettingsSpec `json:"parameters,omitempty"`
}
// +kubebuilder:object:generate=true
......@@ -44,6 +44,16 @@ type ContainerSpec struct {
// container images in workload controllers like Deployments and StatefulSets.
// +optional
Image string `json:"image,omitempty"`
// Entrypoint array. Not executed within a shell.
// The docker image's ENTRYPOINT is used if this is not provided.
// Variable references $(VAR_NAME) are expanded using the container's environment. If a variable
// cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax
// can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded,
// regardless of whether the variable exists or not.
// Cannot be updated.
// More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell
// +optional
Command []string `json:"command,omitempty" protobuf:"bytes,3,rep,name=command"`
// Arguments to the entrypoint.
// The docker image's CMD is used if this is not provided.
// Variable references $(VAR_NAME) are expanded using the container's environment. If a variable
......@@ -61,12 +71,6 @@ type ContainerSpec struct {
// listening on the default "0.0.0.0" address inside a container will be
// accessible from the network.
// Cannot be updated.
// +optional
// +patchMergeKey=containerPort
// +patchStrategy=merge
// +listType=map
// +listMapKey=containerPort
// +listMapKey=protocol
Ports []corev1.ContainerPort `json:"ports,omitempty"`
// Image pull policy.
// One of Always, Never, IfNotPresent.
......@@ -103,3 +107,14 @@ func (c *ContainerSpec) GetContainerPorts() []corev1.ContainerPort { return
func (c *ContainerSpec) GetContainerLivenessProbe() *corev1.Probe { return c.LivenessProbe }
func (c *ContainerSpec) GetContainerReadinessProbe() *corev1.Probe { return c.ReadinessProbe }
func (c *ContainerSpec) GetContainerArgs() []string { return c.Args }
func (c *ContainerSpec) GetContainerCommand() []string { return c.Command }
func (obj *Container) Init() {
if obj.ContainerSpec == nil {
obj.ContainerSpec = &ContainerSpec{}
}
if obj.SettingsSpec == nil {
obj.SettingsSpec = &parameters.SettingsSpec{}
}
}