Skip to content
Commits on Source (15)
/*
Licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.gnu.org/licenses/agpl-3.0.html
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package application package application
import ( import (
......
/* /*
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 https://www.gnu.org/licenses/agpl-3.0.html
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
...@@ -33,7 +33,7 @@ import ( ...@@ -33,7 +33,7 @@ import (
type Network struct { type Network struct {
IngressMeta *meta.ObjectMeta `json:"ingressMeta,omitempty"` IngressMeta *meta.ObjectMeta `json:"ingressMeta,omitempty"`
ServiceMeta *meta.ObjectMeta `json:"serviceMeta,omitempty"` ServiceMeta *meta.ObjectMeta `json:"serviceMeta,omitempty"`
*Backend `json:"backend,inline"` *Backend `json:",inline"`
} }
type Service struct { type Service struct {
......
/* /*
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 https://www.gnu.org/licenses/agpl-3.0.html
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
...@@ -20,8 +20,12 @@ import ( ...@@ -20,8 +20,12 @@ import (
meta "k8s.libre.sh/meta" meta "k8s.libre.sh/meta"
"k8s.libre.sh/objects" "k8s.libre.sh/objects"
deployment "k8s.libre.sh/objects/deployment" deployment "k8s.libre.sh/objects/deployment"
corev1 "k8s.io/api/core/v1"
) )
const DefaultComponent string = "app"
// +kubebuilder:object:generate=true // +kubebuilder:object:generate=true
type Workload struct { type Workload struct {
*meta.ObjectMeta `json:"commonMeta,omitempty"` *meta.ObjectMeta `json:"commonMeta,omitempty"`
...@@ -66,8 +70,8 @@ func (w *Workload) GetObjects() map[int]objects.Object { ...@@ -66,8 +70,8 @@ func (w *Workload) GetObjects() map[int]objects.Object {
return objects return objects
} }
func (w *Workload) SetDependencies(s *Settings) { w.ConfigSpec = s.ConfigSpec } func (w *Workload) SetDependencies(s *settings.Component) { w.ConfigSpec = s.ConfigSpec }
func (w *Workload) GetDependencies() settings.Config { return w.ConfigSpec } func (w *Workload) GetDependencies() settings.Config { return w.ConfigSpec }
func (w *Workload) SetDefaults() { func (w *Workload) SetDefaults() {
...@@ -75,13 +79,22 @@ func (w *Workload) SetDefaults() { ...@@ -75,13 +79,22 @@ func (w *Workload) SetDefaults() {
w.Dependencies = true w.Dependencies = true
w.Backend.ServiceName = w.ServiceMeta.GetName() w.Backend.ServiceName = w.ServiceMeta.GetName()
containerPort := corev1.ContainerPort{
Name: w.Backend.Port.Name,
ContainerPort: w.Backend.Port.Port,
Protocol: w.Backend.Port.Protocol,
}
w.ContainerSpec.Ports = append(w.ContainerSpec.Ports, containerPort)
} }
func (w *Workload) Init() { func (w *Workload) Init() {
// TODO improve initialisation of objectMeta, labels... // TODO improve initialisation of objectMeta, labels...
if w.ObjectMeta == nil { if w.ObjectMeta == nil {
w.ObjectMeta = new(meta.ObjectMeta) w.ObjectMeta = &meta.ObjectMeta{}
} }
if len(w.ObjectMeta.Labels) == 0 { if len(w.ObjectMeta.Labels) == 0 {
...@@ -89,14 +102,16 @@ func (w *Workload) Init() { ...@@ -89,14 +102,16 @@ func (w *Workload) Init() {
} }
// TODO FIXME // TODO FIXME
w.ObjectMeta.SetComponent("app") if len(w.ObjectMeta.GetComponent()) == 0 {
w.ObjectMeta.SetComponent(DefaultComponent)
}
if w.Deployment.ObjectMeta == nil { if w.Deployment.ObjectMeta == nil {
w.Deployment.ObjectMeta = new(meta.ObjectMeta) w.Deployment.ObjectMeta = &meta.ObjectMeta{}
} }
if w.ConfigSpec == nil { if w.ConfigSpec == nil {
w.ConfigSpec = new(settings.ConfigSpec) w.ConfigSpec = &settings.ConfigSpec{}
} }
if w.Backend == nil { if w.Backend == nil {
...@@ -104,10 +119,10 @@ func (w *Workload) Init() { ...@@ -104,10 +119,10 @@ func (w *Workload) Init() {
} }
if w.ServiceMeta == nil { if w.ServiceMeta == nil {
w.ServiceMeta = new(meta.ObjectMeta) w.ServiceMeta = &meta.ObjectMeta{}
} }
if w.IngressMeta == nil { if w.IngressMeta == nil {
w.IngressMeta = new(meta.ObjectMeta) w.IngressMeta = &meta.ObjectMeta{}
} }
} }
...@@ -75,40 +75,6 @@ func (in *Network) DeepCopy() *Network { ...@@ -75,40 +75,6 @@ func (in *Network) DeepCopy() *Network {
return 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.CommonMeta != nil {
in, out := &in.CommonMeta, &out.CommonMeta
*out = new(meta.ObjectMeta)
(*in).DeepCopyInto(*out)
}
if in.SecretMeta != nil {
in, out := &in.SecretMeta, &out.SecretMeta
*out = new(meta.ObjectMeta)
(*in).DeepCopyInto(*out)
}
if in.ConfigMeta != nil {
in, out := &in.ConfigMeta, &out.ConfigMeta
*out = new(meta.ObjectMeta)
(*in).DeepCopyInto(*out)
}
if in.ConfigSpec != nil {
in, out := &in.ConfigSpec, &out.ConfigSpec
*out = (*in).DeepCopy()
}
}
// 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(Settings)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Workload) DeepCopyInto(out *Workload) { func (in *Workload) DeepCopyInto(out *Workload) {
*out = *in *out = *in
......
/*
Licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.gnu.org/licenses/agpl-3.0.html
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package application package application
import ( import (
...@@ -5,7 +20,6 @@ import ( ...@@ -5,7 +20,6 @@ import (
"github.com/presslabs/controller-util/syncer" "github.com/presslabs/controller-util/syncer"
"k8s.libre.sh/application/components"
settings "k8s.libre.sh/application/settings" settings "k8s.libre.sh/application/settings"
"k8s.libre.sh/interfaces" "k8s.libre.sh/interfaces"
"k8s.libre.sh/meta" "k8s.libre.sh/meta"
...@@ -16,7 +30,8 @@ type Instance interface { ...@@ -16,7 +30,8 @@ type Instance interface {
meta.Instance meta.Instance
GetComponents() map[int]Component GetComponents() map[int]Component
GetOwner() interfaces.Object GetOwner() interfaces.Object
GetSettings() Settings GetSettings() settings.Settings
// GetSettings() map[int]settings.Settings
SetDefaults() SetDefaults()
} }
...@@ -54,7 +69,7 @@ func NewSyncers(app Instance, r interfaces.Reconcile, owner interfaces.Object) ( ...@@ -54,7 +69,7 @@ func NewSyncers(app Instance, r interfaces.Reconcile, owner interfaces.Object) (
// TODO TO FIX SHOULD BE RUN IN INITIALIZED FUNCTION // TODO TO FIX SHOULD BE RUN IN INITIALIZED FUNCTION
// INITIALISE VALUES FROM EXTERNAL RESOURCES, RANDOM & TEMPLATES // INITIALISE VALUES FROM EXTERNAL RESOURCES, RANDOM & TEMPLATES
// sett := app.GetSettings().GetConfig().(*components.Settings) // sett := app.GetSettings().GetConfig().(*components.Settings)
sett := app.GetSettings().(*components.Settings) sett := app.GetSettings().(*settings.Component)
err = sett.Init(r.GetClient()) err = sett.Init(r.GetClient())
...@@ -69,7 +84,7 @@ func NewSyncers(app Instance, r interfaces.Reconcile, owner interfaces.Object) ( ...@@ -69,7 +84,7 @@ func NewSyncers(app Instance, r interfaces.Reconcile, owner interfaces.Object) (
s := objects.NewObjectSyncer(obj, owner, r) s := objects.NewObjectSyncer(obj, owner, r)
if err := syncer.Sync(context.TODO(), s, r.GetRecorder()); err != nil { if err := syncer.Sync(context.TODO(), s, r.GetRecorder()); err != nil {
// return nil, err return syncers, err
} }
} }
......
/* /*
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 https://www.gnu.org/licenses/agpl-3.0.html
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
...@@ -13,13 +13,14 @@ See the License for the specific language governing permissions and ...@@ -13,13 +13,14 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package components package settings
import ( import (
"strings"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"k8s.libre.sh/application/settings"
"k8s.libre.sh/application/settings/parameters" "k8s.libre.sh/application/settings/parameters"
"k8s.libre.sh/meta" "k8s.libre.sh/meta"
"k8s.libre.sh/objects" "k8s.libre.sh/objects"
...@@ -27,70 +28,123 @@ import ( ...@@ -27,70 +28,123 @@ import (
"k8s.libre.sh/objects/secret" "k8s.libre.sh/objects/secret"
) )
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 SettingsGenerate string
type SettingsType string
// +kubebuilder:object:generate=true
type Component struct {
CommonMeta *meta.ObjectMeta `json:"commonMeta,omitempty"`
SecretMeta *meta.ObjectMeta `json:"secretMeta,omitempty"`
ConfigMeta *meta.ObjectMeta `json:"configMeta,omitempty"`
// DefaultType parameters.ParameterType `json:"defaultType,omitempty"`
// DefaultMountType parameters.MountType `json:"defaultMountType,omitempty"`
// Template string json:"template,omitempty"`
Generate SettingsGenerate `json:"generate,omitempty"`
SettingsType SettingsType `json:"type,omitempty"`
*ConfigSpec `json:",inline"`
}
// ConfigSpec 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 // +kubebuilder:object:generate=true
type Settings struct { type SettingsSpec struct {
CommonMeta *meta.ObjectMeta `json:"commonMeta,omitempty"` Sources []Source `json:"sources,omitempty"`
SecretMeta *meta.ObjectMeta `json:"secretMeta,omitempty"` // Parameters is a list of parameters
ConfigMeta *meta.ObjectMeta `json:"configMeta,omitempty"` *parameters.Parameters `json:"parameters,omitempty"`
DefaultType parameters.ParameterType `json:"defaultType,omitempty"` }
DefaultMountType parameters.MountType `json:"defaultMountType,omitempty"`
// Template string `json:"template,omitempty"` type CreateOptions struct {
*settings.ConfigSpec `json:",inline"` CommonMeta *meta.ObjectMeta `json:"commonMeta,omitempty"`
SecretMeta *meta.ObjectMeta `json:"secretMeta,omitempty"`
ConfigMeta *meta.ObjectMeta `json:"configMeta,omitempty"`
// DefaultType parameters.ParameterType `json:"defaultType,omitempty"`
// DefaultMountType parameters.MountType `json:"defaultMountType,omitempty"`
// Template string json:"template,omitempty"`
Generate SettingsGenerate `json:"generate,omitempty"`
SettingsType SettingsType `json:"type,omitempty"`
} }
func (s *Settings) GetConfig() settings.Config { return s.ConfigSpec } func (s *Component) GetConfig() Config { return s.ConfigSpec }
func (s *Settings) GetMeta() meta.Instance { return s.CommonMeta } func (s *Component) GetMeta() meta.Instance { return s.CommonMeta }
func (s *Settings) GetSecretMeta() meta.Instance { return s.SecretMeta } func (s *Component) GetSecretMeta() meta.Instance { return s.SecretMeta }
func (s *Settings) GetConfigMapMeta() meta.Instance { return s.ConfigMeta } func (s *Component) GetConfigMapMeta() meta.Instance { return s.ConfigMeta }
func (s *Settings) SetDefaults() { func (s *Component) SetDefaults() {
// TODO TO FIX DUPLICATE WITH INIT // TODO TO FIX DUPLICATE WITH INIT
meta.SetObjectMeta(s.CommonMeta, s.SecretMeta) meta.SetObjectMeta(s.CommonMeta, s.SecretMeta)
meta.SetObjectMeta(s.CommonMeta, s.ConfigMeta) meta.SetObjectMeta(s.CommonMeta, s.ConfigMeta)
} }
func (s *Settings) GetObjects() map[int]objects.Object { func (s *Component) GetObjects() map[int]objects.Object {
cm := &configmap.ConfigMap{ cm := &configmap.ConfigMap{
ObjectMeta: s.GetConfigMapMeta().(*meta.ObjectMeta), ObjectMeta: s.ConfigMeta,
} }
secret := &secret.Secret{ secret := &secret.Secret{
ObjectMeta: s.GetSecretMeta().(*meta.ObjectMeta), ObjectMeta: s.SecretMeta,
} }
objs := make(map[int]objects.Object, 2) objs := make(map[int]objects.Object, 2)
// meta.SetObjectMeta(s.CommonMeta, cm.ObjectMeta) genConfigParams := []string{}
// meta.SetObjectMeta(s.CommonMeta, secret.ObjectMeta) genSecretParams := []string{}
// TODO REPLACE BY GET SECRET PARAMETERS & GET CONFIG PARAMETERS for _, p := range *s.ConfigSpec.Parameters {
// params := s.GetConfig() // TODO TO FIX
for _, p := range *s.ConfigSpec.GetParameters() {
// TODO check not mountLiteral ??
if p.MountType == parameters.MountEnvFile && if p.MountType == parameters.MountEnvFile &&
p.Type == parameters.SecretParameter && // TODO TO FIX
(p.Type == parameters.SecretParameter || p.Type == "") &&
len(p.Value) > 0 { len(p.Value) > 0 {
if p.Generate != parameters.GenerateTemplate && p.Generate != "" {
genSecretParams = append(genSecretParams, p.Key)
}
secret.Parameters = append(secret.Parameters, p) secret.Parameters = append(secret.Parameters, p)
} }
if p.MountType == parameters.MountEnvFile && if p.MountType == parameters.MountEnvFile &&
p.Type == parameters.ConfigParameter && p.Type == parameters.ConfigParameter &&
len(p.Value) > 0 { len(p.Value) > 0 {
if p.Generate != parameters.GenerateTemplate && p.Generate != "" {
genConfigParams = append(genConfigParams, p.Key)
}
cm.Parameters = append(cm.Parameters, p) cm.Parameters = append(cm.Parameters, p)
} }
} }
if len(genSecretParams) > 0 {
if len(secret.ObjectMeta.Annotations) == 0 {
secret.ObjectMeta.Annotations = make(map[string]string)
}
secret.ObjectMeta.Annotations["settings.k8s.libre.sh/generate"] = strings.Join(genSecretParams, ",")
}
if len(genConfigParams) > 0 {
if len(secret.ObjectMeta.Annotations) == 0 {
cm.ObjectMeta.Annotations = make(map[string]string)
}
secret.ObjectMeta.Annotations["settings.k8s.libre.sh/generate"] = strings.Join(genConfigParams, ",")
}
// TODO IMPROVE // TODO IMPROVE
if len(cm.Parameters) > 0 { if len(cm.Parameters) > 0 {
objs[0] = cm objs[0] = cm
} }
if len(secret.Parameters) > 0 { if len(secret.Parameters) > 0 {
// secret.Parameters = secretParameters
if objs[0] == nil { if objs[0] == nil {
objs[0] = secret objs[0] = secret
...@@ -102,11 +156,11 @@ func (s *Settings) GetObjects() map[int]objects.Object { ...@@ -102,11 +156,11 @@ func (s *Settings) GetObjects() map[int]objects.Object {
return objs return objs
} }
func (s *Settings) Init(c client.Client) error { func (s *Component) Init(c client.Client) error {
// TODO TO FIX DUPLICATE WITH SETDEFAULTS // TODO TO FIX DUPLICATE WITH SETDEFAULTS
meta.SetObjectMeta(s.CommonMeta, s.ConfigMeta) meta.SetObjectMeta(s.CommonMeta, s.ConfigMeta)
meta.SetObjectMeta(s.CommonMeta, s.SecretMeta) meta.SetObjectMeta(s.CommonMeta, s.SecretMeta)
// TODO ADD SECRET REFS HERE ??
err := InitParametersValueFrom(s, c) err := InitParametersValueFrom(s, c)
if err != nil { if err != nil {
...@@ -117,17 +171,22 @@ func (s *Settings) Init(c client.Client) error { ...@@ -117,17 +171,22 @@ func (s *Settings) Init(c client.Client) error {
err = s.InitTemplateValues(parameters.KeyPairValues(s.Parameters)) err = s.InitTemplateValues(parameters.KeyPairValues(s.Parameters))
if err != nil {
return err
}
return nil return nil
} }
// InitParametersValueFrom intialise the paremeters with values provided in external resources (secrets and configmaps) in the same namespace // InitParametersValueFrom intialise the parameters with values provided in external resources in the same namespace
// All parameters values are filled from those resources // All parameters values are filled from those resources
func InitParametersValueFrom(s *Settings, c client.Client) error { // Only Secrets and Configmaps are supported
func InitParametersValueFrom(s *Component, c client.Client) error {
params := parameters.Parameters{} params := parameters.Parameters{}
paramsByKey := parameters.ParametersByKey(s.Parameters) paramsByKey := parameters.ParametersByKey(s.Parameters)
paramsBySecretSource, paramsByConfigMapSource := settings.OrderByResourceRef(s.ConfigSpec) paramsBySecretSource, paramsByConfigMapSource := OrderByResourceRef(s.ConfigSpec)
cm := &corev1.ConfigMap{} cm := &corev1.ConfigMap{}
sec := &corev1.Secret{} sec := &corev1.Secret{}
...@@ -137,6 +196,7 @@ func InitParametersValueFrom(s *Settings, c client.Client) error { ...@@ -137,6 +196,7 @@ func InitParametersValueFrom(s *Settings, c client.Client) error {
for k, v := range paramsBySecretSource { for k, v := range paramsBySecretSource {
sec.SetName(k) sec.SetName(k)
err := parameters.GetAndMergeParameters(v, paramsByKey, c, sec) err := parameters.GetAndMergeParameters(v, paramsByKey, c, sec)
if err != nil { if err != nil {
return err return err
...@@ -151,26 +211,93 @@ func InitParametersValueFrom(s *Settings, c client.Client) error { ...@@ -151,26 +211,93 @@ func InitParametersValueFrom(s *Settings, c client.Client) error {
} }
} }
secretSrc := Source{
Ref: s.GetSecretMeta().GetName(),
Type: "secret",
}
configSrc := Source{
Ref: s.GetSecretMeta().GetName(),
Type: "configmap",
}
if s.Generate == GenEnvFile {
// s.SecretRefs = []string{s.GetSecretMeta().GetName()}
// s.ConfigRefs = []string{s.GetConfigMapMeta().GetName()}
s.Sources = []Source{}
if len(paramsByConfigMapSource) > 0 {
s.Sources = append(s.Sources, configSrc)
}
if len(paramsBySecretSource) > 0 {
s.Sources = append(s.Sources, secretSrc)
}
for _, v := range paramsByKey {
v.MountType = parameters.MountEnvFile
v.Ref = ""
params = append(params, v)
}
s.Parameters = &params
return nil
}
addSecretSrc := false
addConfigSrc := false
for _, v := range paramsByKey { for _, v := range paramsByKey {
if v.MountType == parameters.MountEnvFile { if v.MountType == parameters.MountEnvFile {
if v.Type == parameters.ConfigParameter { v.Ref = ""
v.Ref = s.GetConfigMapMeta().GetName()
} if !addConfigSrc && v.Type == parameters.ConfigParameter {
if v.Type == parameters.SecretParameter { s.Sources = append(s.Sources, configSrc)
v.Ref = s.GetSecretMeta().GetName() addConfigSrc = true
} else if !addSecretSrc && v.Type == parameters.SecretParameter {
s.Sources = append(s.Sources, secretSrc)
addSecretSrc = true
} }
} }
params = append(params, v) params = append(params, v)
} }
// if defaultMountType == EnvFile {
// }
// TODO FIX THIS we need to check if we want to mount as EnvFile and reset old resources references
s.SecretRefs = []string{}
s.ConfigRefs = []string{}
s.Parameters = &params s.Parameters = &params
return nil return nil
} }
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
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)
}
if in.Parameters != nil {
in, out := &in.Parameters, &out.Parameters
*out = new(parameters.Parameters)
if **in != nil {
in, out := *in, *out
*out = make([]*parameters.Parameter, len(*in))
for i := range *in {
if (*in)[i] != nil {
in, out := &(*in)[i], &(*out)[i]
*out = new(parameters.Parameter)
**out = **in
}
}
}
}
}
// 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(SettingsSpec)
in.DeepCopyInto(out)
return out
}
/* /*
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 https://www.gnu.org/licenses/agpl-3.0.html
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
...@@ -13,22 +13,47 @@ See the License for the specific language governing permissions and ...@@ -13,22 +13,47 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
// Package settings provides some api types and interfaces to manage settings in kubernetes
//
// Settings can be provided in:
// - The parent CRD with the parameter type
// - ConfigMaps and Secrets
//
// Settings can be passed to a container:
// - As EnvVar in the container spec (name & value)
// - As EnvVarFrom in the container spec with a fromKey and secret/configMap source
// - As EnvVarFrom object
// - As EnvFrom mounting all the data from a secret/configmap as env var
// - As a file configmap/secret
//
// Settings value:
// - can be randomly generate
// - provided in the crd
// - generate by template
package settings package settings
import ( import (
"sort"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.libre.sh/application/settings/parameters" "k8s.libre.sh/application/settings/parameters"
"k8s.libre.sh/utils"
) )
// ConfigSpec defines a list of parameters and some sources from which those parameters can be fetched // +kubebuilder:object:generate=true
// It can be used in the conta type Source struct {
// Ref is the name of a resource in the same namespace
Ref string `json:"ref,omitempty"`
// Type is the type of the resource
// Only Secrets and ConfigMaps are supported
Type string `json:"type,omitempty"`
}
// ConfigSpec 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 // +kubebuilder:object:generate=true
type ConfigSpec struct { type ConfigSpec struct {
// SecretRefs is a list of secrets in the name namespace // Sources is a list of sources for the parameters from kubernetes resources in the same namespace
SecretRefs []string `json:"secretRefs,omitempty"` Sources []Source `json:"sources,omitempty"`
// ConfigRefs is a list of configmaps in the name namespace
ConfigRefs []string `json:"configRefs,omitempty"`
// Parameters is a list of parameters // Parameters is a list of parameters
*parameters.Parameters `json:"parameters,omitempty"` *parameters.Parameters `json:"parameters,omitempty"`
} }
...@@ -39,94 +64,120 @@ func (c *ConfigSpec) SetParameters(parameters *parameters.Parameters) { c.Parame ...@@ -39,94 +64,120 @@ func (c *ConfigSpec) SetParameters(parameters *parameters.Parameters) { c.Parame
// GetParameters return the parameters // GetParameters return the parameters
func (c *ConfigSpec) GetParameters() *parameters.Parameters { func (c *ConfigSpec) GetParameters() *parameters.Parameters {
if c.Parameters == nil { if c.Parameters == nil {
c.Parameters = new(parameters.Parameters) c.Parameters = &parameters.Parameters{}
} }
return c.Parameters return c.Parameters
} }
func (c *ConfigSpec) GetConfigRefs() []string { return c.ConfigRefs } func (c *ConfigSpec) GetSources() []Source { return c.Sources }
func (c *ConfigSpec) SetConfigRefs(refs []string) { c.ConfigRefs = refs }
func (c *ConfigSpec) GetSecretRefs() []string { return c.SecretRefs }
func (c *ConfigSpec) SetSecretRefs(refs []string) { c.SecretRefs = refs } func (c *ConfigSpec) SetSources(sources []Source) { c.Sources = sources }
// GetEnvFrom returns a list of sources to populate environment variables in the container. // GetEnvFrom returns a list of EnvFromSource to populate environment variables in the container.
func (c *ConfigSpec) GetEnvFrom() []corev1.EnvFromSource { func (c *ConfigSpec) GetEnvFrom() []corev1.EnvFromSource {
envFroms := []corev1.EnvFromSource{} // envFroms := []corev1.EnvFromSource{}
envFromSecret := []corev1.EnvFromSource{}
envFromConfigMap := []corev1.EnvFromSource{}
// envFromMap := map[int]corev1.EnvFromSource{}
envFrom := corev1.EnvFromSource{} envFrom := corev1.EnvFromSource{}
src := Source{}
for _, p := range *c.Parameters { for _, p := range *c.Parameters {
if len(p.Ref) > 0 { if p.MountType == parameters.MountEnvFile && len(p.Ref) > 0 {
if p.MountType == parameters.MountEnvFile { if p.Type == parameters.ConfigParameter {
if p.Type == parameters.ConfigParameter { src = Source{
c.ConfigRefs = append(c.ConfigRefs, p.Ref) Ref: p.Ref,
} else if p.Type != parameters.ObjectFieldParameter { Type: string(p.Type),
c.SecretRefs = append(c.SecretRefs, p.Ref) }
c.Sources = append(c.Sources, src)
} else if p.Type == parameters.SecretParameter {
src = Source{
Ref: p.Ref,
Type: string(p.Type),
} }
c.Sources = append(c.Sources, src)
} }
} }
} }
c.SecretRefs = utils.Unique(c.SecretRefs) if len(c.Sources) > 0 {
c.ConfigRefs = utils.Unique(c.ConfigRefs) for _, source := range c.Sources {
if source.Type == "configmap" {
if len(c.ConfigRefs) > 0 { envFrom = corev1.EnvFromSource{
for _, configRef := range c.ConfigRefs { ConfigMapRef: &corev1.ConfigMapEnvSource{
envFrom = corev1.EnvFromSource{ LocalObjectReference: corev1.LocalObjectReference{
ConfigMapRef: &corev1.ConfigMapEnvSource{ Name: source.Ref,
LocalObjectReference: corev1.LocalObjectReference{ },
Name: configRef,
}, },
}, }
} // envFromMap[k] = envFrom
envFroms = append(envFroms, envFrom) envFromConfigMap = append(envFromConfigMap, envFrom)
} } else if source.Type == "secret" {
} envFrom = corev1.EnvFromSource{
SecretRef: &corev1.SecretEnvSource{
if len(c.SecretRefs) > 0 { LocalObjectReference: corev1.LocalObjectReference{
for _, secretRef := range c.SecretRefs { Name: source.Ref,
envFrom = corev1.EnvFromSource{ },
SecretRef: &corev1.SecretEnvSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: secretRef,
}, },
}, }
// envFromMap[k] = envFrom
envFromSecret = append(envFromSecret, envFrom)
} }
envFroms = append(envFroms, envFrom)
} }
} }
if len(envFroms) > 0 { // We need to sort so the order is always the same and container is not update
return envFroms // if len(envFromSecret) > 0 {
} sort.SliceStable(envFromSecret, func(i, j int) bool {
return envFromSecret[i].SecretRef.Name < envFromSecret[j].SecretRef.Name
return nil })
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
} }
// We need to manually change this autogenerated function as it is broken with Paramete drs type, its trying to do new([]*Parameter) instead of new(Parameters)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-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 *ConfigSpec) DeepCopyInto(out *ConfigSpec) {
*out = *in *out = *in
if in.SecretRefs != nil { if in.Sources != nil {
in, out := &in.SecretRefs, &out.SecretRefs in, out := &in.Sources, &out.Sources
*out = make([]string, len(*in)) *out = make([]Source, len(*in))
copy(*out, *in)
}
if in.ConfigRefs != nil {
in, out := &in.ConfigRefs, &out.ConfigRefs
*out = make([]string, len(*in))
copy(*out, *in) copy(*out, *in)
} }
if in.Parameters != nil { if in.Parameters != nil {
in, out := &in.Parameters, &out.Parameters in, out := &in.Parameters, &out.Parameters
*out = new(parameters.Parameters) *out = new(parameters.Parameters)
(*in).DeepCopyInto(*out) if **in != nil {
in, out := *in, *out
*out = make([]*parameters.Parameter, len(*in))
for i := range *in {
if (*in)[i] != nil {
in, out := &(*in)[i], &(*out)[i]
*out = new(parameters.Parameter)
**out = **in
}
}
}
} }
} }
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Settings. // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec.
func (in *ConfigSpec) DeepCopy() *ConfigSpec { func (in *ConfigSpec) DeepCopy() *ConfigSpec {
if in == nil { if in == nil {
return nil return nil
......
/* /*
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 https://www.gnu.org/licenses/agpl-3.0.html
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
...@@ -15,17 +15,18 @@ limitations under the License. ...@@ -15,17 +15,18 @@ limitations under the License.
package settings package settings
import "k8s.libre.sh/application/settings/parameters" import (
"k8s.libre.sh/application/settings/parameters"
)
type Config interface { type Config interface {
GetConfigRefs() []string
SetConfigRefs([]string)
GetParameters() *parameters.Parameters GetParameters() *parameters.Parameters
SetParameters(*parameters.Parameters) SetParameters(*parameters.Parameters)
GetSecretRefs() []string
SetSecretRefs([]string)
InitRandValues() InitRandValues()
InitTemplateValues(map[string]string) error InitTemplateValues(map[string]string) error
// InitExternaValues(c client.Client) error
SetSources(sources []Source)
GetSources() (sources []Source)
} }
func MergeSettings(src, dest Config) Config { func MergeSettings(src, dest Config) Config {
...@@ -33,8 +34,7 @@ func MergeSettings(src, dest Config) Config { ...@@ -33,8 +34,7 @@ func MergeSettings(src, dest Config) Config {
if dest == nil { if dest == nil {
dest = src dest = src
} else { } else {
dest.SetConfigRefs(append(dest.GetConfigRefs(), src.GetConfigRefs()...)) dest.SetSources(append(dest.GetSources(), src.GetSources()...))
dest.SetSecretRefs(append(dest.GetSecretRefs(), src.GetSecretRefs()...))
params := *dest.GetParameters() params := *dest.GetParameters()
......
/* /*
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 https://www.gnu.org/licenses/agpl-3.0.html
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
...@@ -31,11 +31,12 @@ const ( ...@@ -31,11 +31,12 @@ const (
// Parameter is mounted as key/value in the container envVar specs // Parameter is mounted as key/value in the container envVar specs
MountLiteral MountType = "literal" MountLiteral MountType = "literal"
// Parameter is mounted as as EnvVarSource in the container envVar specs // Parameter is mounted as as EnvVarSource in the container envVar specs
// no data is transformed // no data is transformed in a new resource
MountFrom MountType = "from" MountFrom MountType = "from"
// Parameter is mouned as file in the container path
MountFile MountType = "file" MountFile MountType = "file"
// Parameter is mounted as EnvFromSource in the container specs // Parameter is mounted as EnvFromSource in the container specs
// Data can be retrieved from the the crds or external resources specified in the envFrom // Data can be retrieved from the crds or external resources specified in the parameter envFrom
// and transformed in a new secret or configmap // and transformed in a new secret or configmap
MountEnvFile MountType = "envFile" MountEnvFile MountType = "envFile"
) )
...@@ -58,9 +59,11 @@ type Parameters []*Parameter ...@@ -58,9 +59,11 @@ type Parameters []*Parameter
type Parameter struct { type Parameter struct {
// Key of the parameter, can be mounted as as an environment variable, used in template // Key of the parameter, can be mounted as as an environment variable, used in template
// or as in the data fied of configmap/secret // or as in the data fied of configmap/secret
//
// Key must be unique
Key string `json:"key,omitempty"` Key string `json:"key,omitempty"`
// Value of the paramater, should not contain secret values // Value of the paramater, should not contain secret values
// It can be a template, ParameterType should be template // If it is a template, ParameterType should be template
Value string `json:"value,omitempty"` Value string `json:"value,omitempty"`
// ValueFrom when specified indicates the source of the parameter. // ValueFrom when specified indicates the source of the parameter.
// Cannot be used if value is not empty. // Cannot be used if value is not empty.
...@@ -81,9 +84,9 @@ type ValueFrom struct { ...@@ -81,9 +84,9 @@ type ValueFrom struct {
FromKey string `json:"fromKey,omitempty"` FromKey string `json:"fromKey,omitempty"`
// Name of the referent. // Name of the referent.
Ref string `json:"ref,omitempty"` Ref string `json:"ref,omitempty"`
// Type of the source othe parameter // Type of the parameter's source
// Defaults to the parameter type if not specified // Defaults to the parameter type if not specified
Type ParameterType `json:"type,omitempty"` RefType ParameterType `json:"refType,omitempty"`
} }
type MountPath struct { type MountPath struct {
......
/* /*
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 https://www.gnu.org/licenses/agpl-3.0.html
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
...@@ -23,7 +23,6 @@ import ( ...@@ -23,7 +23,6 @@ import (
// GetEnvVar gets an environment variables to set in the container. // GetEnvVar gets an environment variables to set in the container.
func (p *Parameter) GetEnvVar() (envVar corev1.EnvVar, err error) { func (p *Parameter) GetEnvVar() (envVar corev1.EnvVar, err error) {
switch p.MountType { switch p.MountType {
case MountLiteral: case MountLiteral:
if len(p.Value) > 0 && len(p.Key) > 0 { if len(p.Value) > 0 && len(p.Key) > 0 {
......
/* /*
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 https://www.gnu.org/licenses/agpl-3.0.html
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
...@@ -17,13 +17,11 @@ package parameters ...@@ -17,13 +17,11 @@ package parameters
import ( import (
"bytes" "bytes"
"context" "sort"
"text/template" "text/template"
"github.com/presslabs/controller-util/rand" "github.com/presslabs/controller-util/rand"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.libre.sh/interfaces"
"sigs.k8s.io/controller-runtime/pkg/client"
) )
func (p *Parameters) InitValues() { func (p *Parameters) InitValues() {
...@@ -89,7 +87,8 @@ func (p *Parameters) GetData() map[string]string { ...@@ -89,7 +87,8 @@ func (p *Parameters) GetData() map[string]string {
data := make(map[string]string) data := make(map[string]string)
for _, param := range *p { for _, param := range *p {
if param.MountType == MountEnvFile && // TODO TO FIX
if (param.MountType == MountEnvFile || param.MountType == "") &&
param.Type != ObjectFieldParameter && param.Type != ObjectFieldParameter &&
len(param.Value) > 0 { len(param.Value) > 0 {
data[param.Key] = param.Value data[param.Key] = param.Value
...@@ -108,7 +107,7 @@ func (p *Parameters) GetEnvVar() []corev1.EnvVar { ...@@ -108,7 +107,7 @@ func (p *Parameters) GetEnvVar() []corev1.EnvVar {
for _, param := range *p { for _, param := range *p {
envVar, err = param.GetEnvVar() envVar, err = param.GetEnvVar()
// TODO TOFIX
if err != nil { if err != nil {
} }
...@@ -118,61 +117,12 @@ func (p *Parameters) GetEnvVar() []corev1.EnvVar { ...@@ -118,61 +117,12 @@ func (p *Parameters) GetEnvVar() []corev1.EnvVar {
} }
if len(envVars) > 0 { if len(envVars) > 0 {
return envVars // Sort var to avoid update of the object if var are not in the same order?
} sort.SliceStable(envVars, func(i, j int) bool {
return nil return envVars[i].Name < envVars[j].Name
} })
func GetAndMergeParameters(
params Parameters,
paramsByKey map[string]*Parameter,
c client.Client,
obj interfaces.Object) error {
var pType ParameterType
data := map[string]string{}
objectKey, _ := client.ObjectKeyFromObject(obj)
err := c.Get(context.Background(), objectKey, obj)
if err != nil {
return err
}
// switch obj.GetObjectKind().GroupVersionKind().Kind
if obj.GetObjectKind().GroupVersionKind().Kind == "Secret" { return envVars
pType = SecretParameter
for k, v := range obj.(*corev1.Secret).Data {
data[k] = string(v)
}
}
if obj.GetObjectKind().GroupVersionKind().Kind == "ConfigMap" {
pType = ConfigParameter
for k, v := range obj.(*corev1.ConfigMap).Data {
data[k] = v
}
}
if len(params) > 0 {
for _, pp := range params {
paramsByKey[pp.Key].Value = string(data[pp.FromKey])
}
} else {
for kk, vv := range data {
// TODO TO FIX
if paramsByKey[kk] == nil {
paramsByKey[kk] = new(Parameter)
}
paramsByKey[kk].Value = vv
paramsByKey[kk].Key = kk
// TODO This would be checked if we want to recreate the data or just mount the whole secret
paramsByKey[kk].MountType = MountEnvFile
paramsByKey[kk].Type = pType
}
} }
return nil return nil
} }
/* /*
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 https://www.gnu.org/licenses/agpl-3.0.html
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
...@@ -16,7 +16,14 @@ limitations under the License. ...@@ -16,7 +16,14 @@ limitations under the License.
package parameters package parameters
import ( import (
"context"
"errors"
"reflect" "reflect"
corev1 "k8s.io/api/core/v1"
"k8s.libre.sh/interfaces"
"sigs.k8s.io/controller-runtime/pkg/client"
) )
func Marshal(i interface{}) (Parameters, error) { func Marshal(i interface{}) (Parameters, error) {
...@@ -46,9 +53,9 @@ func Marshal(i interface{}) (Parameters, error) { ...@@ -46,9 +53,9 @@ func Marshal(i interface{}) (Parameters, error) {
parameter.Key = env parameter.Key = env
} }
if len(parameter.MountType) == 0 { // if len(parameter.MountType) == 0 {
parameter.MountType = MountEnvFile // parameter.MountType = MountEnvFile
} // }
parameters = append(parameters, &parameter) parameters = append(parameters, &parameter)
} }
...@@ -56,12 +63,17 @@ func Marshal(i interface{}) (Parameters, error) { ...@@ -56,12 +63,17 @@ func Marshal(i interface{}) (Parameters, error) {
return parameters, nil return parameters, nil
} }
// Sort parameters by keys, it takes the fromKey if it exists // Sort parameters by keys
func ParametersByKey(p *Parameters) map[string]*Parameter { func ParametersByKey(p *Parameters) map[string]*Parameter {
paramsByKey := map[string]*Parameter{} paramsByKey := map[string]*Parameter{}
for _, param := range *p { for _, param := range *p {
/* if len(param.FromKey) > 0 {
paramsByKey[param.FromKey] = param
} else { */
paramsByKey[param.Key] = param paramsByKey[param.Key] = param
// }
} }
return paramsByKey return paramsByKey
} }
...@@ -76,3 +88,62 @@ func KeyPairValues(p *Parameters) map[string]string { ...@@ -76,3 +88,62 @@ func KeyPairValues(p *Parameters) map[string]string {
return data return data
} }
func InitParametersFromResources() {
}
// 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{}
objectKey, _ := client.ObjectKeyFromObject(obj)
err := c.Get(context.Background(), objectKey, obj)
if err != nil {
return 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
}
default:
return 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{}
}
paramsByKey[kk].Value = vv
paramsByKey[kk].Key = kk
// paramsByKey[kk].MountType = MountEnvFile
// TODO TO FIX This should be checked
paramsByKey[kk].Type = pType
}
}
return nil
}
/* /*
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 https://www.gnu.org/licenses/agpl-3.0.html
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
...@@ -13,16 +13,10 @@ See the License for the specific language governing permissions and ...@@ -13,16 +13,10 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package application package settings
import ( import (
"k8s.libre.sh/application/components"
"k8s.libre.sh/application/settings"
"k8s.libre.sh/application/settings/parameters"
"k8s.libre.sh/meta" "k8s.libre.sh/meta"
"k8s.libre.sh/objects"
"k8s.libre.sh/objects/configmap"
"k8s.libre.sh/objects/secret"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
) )
...@@ -31,25 +25,24 @@ type Settings interface { ...@@ -31,25 +25,24 @@ type Settings interface {
GetMeta() meta.Instance GetMeta() meta.Instance
GetSecretMeta() meta.Instance GetSecretMeta() meta.Instance
GetConfigMapMeta() meta.Instance GetConfigMapMeta() meta.Instance
GetConfig() settings.Config GetConfig() Config
SetDefaults() SetDefaults()
Init(c client.Client) error Init(c client.Client) error
} }
func NewSettings(s Settings) *components.Settings { func NewSettings(s Settings) *Component {
return &components.Settings{ return &Component{
CommonMeta: s.GetMeta().(*meta.ObjectMeta), CommonMeta: s.GetMeta().(*meta.ObjectMeta),
SecretMeta: s.GetSecretMeta().(*meta.ObjectMeta), SecretMeta: s.GetSecretMeta().(*meta.ObjectMeta),
ConfigMeta: s.GetConfigMapMeta().(*meta.ObjectMeta), ConfigMeta: s.GetConfigMapMeta().(*meta.ObjectMeta),
ConfigSpec: &settings.ConfigSpec{ ConfigSpec: &ConfigSpec{
ConfigRefs: s.GetConfig().GetConfigRefs(), Sources: s.GetConfig().GetSources(),
SecretRefs: s.GetConfig().GetSecretRefs(),
Parameters: s.GetConfig().GetParameters(), Parameters: s.GetConfig().GetParameters(),
}, },
} }
} }
func GetObjects(s Settings) map[int]objects.Object { /* func GetObjects(s Settings) map[int]objects.Object {
cm := &configmap.ConfigMap{ cm := &configmap.ConfigMap{
ObjectMeta: &meta.ObjectMeta{}, ObjectMeta: &meta.ObjectMeta{},
...@@ -64,12 +57,11 @@ func GetObjects(s Settings) map[int]objects.Object { ...@@ -64,12 +57,11 @@ func GetObjects(s Settings) map[int]objects.Object {
meta.SetObjectMeta(s.GetConfigMapMeta(), cm.ObjectMeta) meta.SetObjectMeta(s.GetConfigMapMeta(), cm.ObjectMeta)
meta.SetObjectMeta(s.GetSecretMeta(), secret.ObjectMeta) meta.SetObjectMeta(s.GetSecretMeta(), secret.ObjectMeta)
// TODO REPLACE BY GET SECRET PARAMETERS & GET CONFIG PARAMETERS
params := s.GetConfig() params := s.GetConfig()
for _, p := range *params.GetParameters() { for _, p := range *params.GetParameters() {
// TODO check not mountLiteral ??
if p.MountType == parameters.MountEnvFile && if p.MountType == parameters.MountEnvFile &&
// TO FIX
p.Type == parameters.SecretParameter && p.Type == parameters.SecretParameter &&
len(p.Value) > 0 { len(p.Value) > 0 {
secret.Parameters = append(secret.Parameters, p) secret.Parameters = append(secret.Parameters, p)
...@@ -97,3 +89,4 @@ func GetObjects(s Settings) map[int]objects.Object { ...@@ -97,3 +89,4 @@ func GetObjects(s Settings) map[int]objects.Object {
return objs return objs
} }
*/
/* /*
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 https://www.gnu.org/licenses/agpl-3.0.html
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
...@@ -17,17 +17,16 @@ package settings ...@@ -17,17 +17,16 @@ package settings
import "k8s.libre.sh/application/settings/parameters" import "k8s.libre.sh/application/settings/parameters"
func OrderByResourceRef(s *ConfigSpec) (secrets, configs map[string]parameters.Parameters) { func OrderByResourceRef(s *ConfigSpec) (secrets, configMaps map[string]parameters.Parameters) {
secrets = make(map[string]parameters.Parameters) secrets = make(map[string]parameters.Parameters)
configs = make(map[string]parameters.Parameters) configMaps = make(map[string]parameters.Parameters)
// We order the parameters by secret and configmap sources for _, source := range s.Sources {
// First we get the sources provided as resources that should be mounted untouched if source.Type == "secret" {
for _, ref := range s.SecretRefs { secrets[source.Ref] = parameters.Parameters{}
secrets[ref] = parameters.Parameters{} } else if source.Type == "configmap" {
} configMaps[source.Ref] = parameters.Parameters{}
for _, ref := range s.ConfigRefs { }
configs[ref] = parameters.Parameters{}
} }
// Then we get the sources that are provided for each parameters and will need a transformation // Then we get the sources that are provided for each parameters and will need a transformation
...@@ -36,8 +35,39 @@ func OrderByResourceRef(s *ConfigSpec) (secrets, configs map[string]parameters.P ...@@ -36,8 +35,39 @@ func OrderByResourceRef(s *ConfigSpec) (secrets, configs map[string]parameters.P
secrets[p.ValueFrom.Ref] = append(secrets[p.ValueFrom.Ref], p) secrets[p.ValueFrom.Ref] = append(secrets[p.ValueFrom.Ref], p)
} }
if len(p.ValueFrom.Ref) > 0 && p.Type == parameters.ConfigParameter { if len(p.ValueFrom.Ref) > 0 && p.Type == parameters.ConfigParameter {
configs[p.ValueFrom.Ref] = append(configs[p.ValueFrom.Ref], p) configMaps[p.ValueFrom.Ref] = append(configMaps[p.ValueFrom.Ref], p)
} }
} }
return secrets, configs
return secrets, configMaps
} }
/*
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
}
*/
// +build !ignore_autogenerated
/*
Licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.gnu.org/licenses/agpl-3.0.html
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by controller-gen. DO NOT EDIT.
package settings
import (
"k8s.libre.sh/meta"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Component) DeepCopyInto(out *Component) {
*out = *in
if in.CommonMeta != nil {
in, out := &in.CommonMeta, &out.CommonMeta
*out = new(meta.ObjectMeta)
(*in).DeepCopyInto(*out)
}
if in.SecretMeta != nil {
in, out := &in.SecretMeta, &out.SecretMeta
*out = new(meta.ObjectMeta)
(*in).DeepCopyInto(*out)
}
if in.ConfigMeta != nil {
in, out := &in.ConfigMeta, &out.ConfigMeta
*out = new(meta.ObjectMeta)
(*in).DeepCopyInto(*out)
}
if in.ConfigSpec != nil {
in, out := &in.ConfigSpec, &out.ConfigSpec
*out = (*in).DeepCopy()
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Component.
func (in *Component) DeepCopy() *Component {
if in == nil {
return nil
}
out := new(Component)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Source) DeepCopyInto(out *Source) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Source.
func (in *Source) DeepCopy() *Source {
if in == nil {
return nil
}
out := new(Source)
in.DeepCopyInto(out)
return out
}
...@@ -3,8 +3,9 @@ module k8s.libre.sh ...@@ -3,8 +3,9 @@ module k8s.libre.sh
go 1.13 go 1.13
require ( require (
github.com/golangci/golangci-lint v1.27.0 // indirect
github.com/onsi/ginkgo v1.12.0 github.com/onsi/ginkgo v1.12.0
github.com/onsi/gomega v1.8.1 github.com/onsi/gomega v1.9.0
github.com/presslabs/controller-util v0.2.2 github.com/presslabs/controller-util v0.2.2
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 // indirect golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 // indirect
k8s.io/api v0.18.1 k8s.io/api v0.18.1
......
This diff is collapsed.
/* /*
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 https://www.gnu.org/licenses/agpl-3.0.html
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
...@@ -25,18 +25,16 @@ import ( ...@@ -25,18 +25,16 @@ import (
// Reconcile is the interface for Reconcile object structs . This // Reconcile is the interface for Reconcile object structs . This
// interface can be used to pass around Reconcile structs commonly // interface can be used to pass around Reconcile structs commonly
// used in Operators. // used in Kubebuilder.
// //
// Note however that by default Reconcile structs generated using // Note however that by default Reconcile structs generated using
// Operator SDK do not implement this interface. Add following // Kubebuilder do not implement this interface. Add following
// functions to implement this interface. // functions to implement this interface.
// //
// func (r *ReconcileObject) GetClient() client.Client { return r.client } // func (r *ReconcileObject) GetClient() client.Client { return r.client }
// func (r *ReconcileObject) GetScheme() *runtime.Scheme { return r.scheme } // func (r *ReconcileObject) GetScheme() *runtime.Scheme { return r.scheme }
// func (r *ReconcileObject) GetScheme() *runtime.Recorder { return r.recorder } // func (r *ReconcileObject) GetScheme() *runtime.Recorder { return r.recorder }
// //
// The Reconcile object structs must implement this interface to use
// Operatorlib functions.
type Reconcile interface { type Reconcile interface {
// Getter function for reconcile client // Getter function for reconcile client
GetClient() client.Client GetClient() client.Client
......
/* /*
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 https://www.gnu.org/licenses/agpl-3.0.html
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
...@@ -21,37 +21,31 @@ import ( ...@@ -21,37 +21,31 @@ import (
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
) )
// TODO remove meta in interface, not needed
// Instance interface can work with the commons app.kubernetes.io labels - https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/#labels
type Instance interface { type Instance interface {
Meta Meta
// The name of the application - app.kubernetes.io/name
GetApplication() string GetApplication() string
SetApplication(string) SetApplication(string)
// A unique name identifying the instance of an application - app.kubernetes.io/instance
GetInstance() string GetInstance() string
SetInstance(string) SetInstance(string)
// The current version of the application (e.g., a semantic version, revision hash, etc.) - app.kubernetes.io/version
GetVersion() string GetVersion() string
SetVersion(string) SetVersion(string)
// The component within the architecture - app.kubernetes.io/component
GetComponent() string GetComponent() string
SetComponent(string) SetComponent(string)
// The name of a higher level application this one is part of - app.kubernetes.io/part-of
GetPartOf() string GetPartOf() string
SetPartOf(string) SetPartOf(string)
// The tool being used to manage the operation of an application - app.kubernetes.io/managed-by
GetManagedBy() string GetManagedBy() string
SetManagedBy(string) SetManagedBy(string)
} }
/* type Application interface { // Instance labels returns the app.kubernetes.io labels
GetApplication() string
SetApplication(string)
GetInstance() string
SetInstance(string)
GetVersion() string
SetVersion(string)
GetComponent() string
SetComponent(string)
GetPartOf() string
SetPartOf(string)
GetManagedBy() string
SetManagedBy(string)
} */
func InstanceLabels(m Instance) map[string]string { func InstanceLabels(m Instance) map[string]string {
labels := labels.Set{ labels := labels.Set{
"app.kubernetes.io/name": m.GetApplication(), "app.kubernetes.io/name": m.GetApplication(),
...@@ -64,6 +58,7 @@ func InstanceLabels(m Instance) map[string]string { ...@@ -64,6 +58,7 @@ func InstanceLabels(m Instance) map[string]string {
return labels return labels
} }
// TODO use Object interface and rename Merge ?
func SetObjectMeta(src Instance, dest Instance) { func SetObjectMeta(src Instance, dest Instance) {
dest.SetLabels(labels.Merge(dest.GetLabels(), InstanceLabels(src))) dest.SetLabels(labels.Merge(dest.GetLabels(), InstanceLabels(src)))
......
/* /*
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 https://www.gnu.org/licenses/agpl-3.0.html
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
...@@ -20,6 +20,10 @@ import ( ...@@ -20,6 +20,10 @@ import (
interfaces "k8s.libre.sh/interfaces" interfaces "k8s.libre.sh/interfaces"
) )
// Meta interface is a stripped down version of https://godoc.org/k8s.io/apimachinery/pkg/apis/meta/v1#Object with
// only user definied specs.
//
// To mutates an object a type must implements this interface
type Meta interface { type Meta interface {
GetLabels() map[string]string GetLabels() map[string]string
SetLabels(labels map[string]string) SetLabels(labels map[string]string)
...@@ -31,6 +35,7 @@ type Meta interface { ...@@ -31,6 +35,7 @@ type Meta interface {
SetNamespace(string) SetNamespace(string)
} }
// MutateMeta mutates an Object meta
func MutateMeta(o Meta, obj interfaces.Object) error { func MutateMeta(o Meta, obj interfaces.Object) error {
obj.SetLabels(o.GetLabels()) obj.SetLabels(o.GetLabels())
...@@ -38,14 +43,5 @@ func MutateMeta(o Meta, obj interfaces.Object) error { ...@@ -38,14 +43,5 @@ func MutateMeta(o Meta, obj interfaces.Object) error {
obj.SetAnnotations(labels.Merge(obj.GetAnnotations(), o.GetAnnotations())) obj.SetAnnotations(labels.Merge(obj.GetAnnotations(), o.GetAnnotations()))
} }
// if len(obj.GetName()) == 0 {
// obj.SetName(o.GetName())
// }
// if len(obj.GetNamespace()) == 0 {
// obj.SetNamespace(o.GetNamespace())
// }
return nil return nil
} }