Skip to content
Commits on Source (2)
package instance
/*
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
import (
"github.com/presslabs/controller-util/syncer"
settings "k8s.libre.sh/application/settings"
interfaces "k8s.libre.sh/interfaces"
parameters "k8s.libre.sh/settings"
meta "k8s.libre.sh/meta"
objects "k8s.libre.sh/objects"
)
type Component interface {
Meta
GetMeta() Meta
SetDefaults(i Instance)
GetObjects() map[int]Object
meta.Instance
GetMeta() meta.Instance
SetDefaults()
Init()
GetObjects() map[int]objects.Object
HasDependencies() bool
GetDependencies() parameters.Interface
// SetDependencies(*parameters.Settings)
GetDependencies() settings.Config
}
func NewSyncer(i Component, r interfaces.Reconcile, owner interfaces.Object) (syncers []syncer.Interface) {
mutators := i.GetObjects()
for _, m := range mutators {
syncers = append(syncers, NewObjectSyncer(m, owner, r))
syncers = append(syncers, objects.NewObjectSyncer(m, owner, r))
}
return syncers
......@@ -30,41 +47,14 @@ func InitComponent(i Instance, c Component) {
component := c.GetComponent()
SetObjectMeta(i, c)
meta.SetObjectMeta(i, c)
if len(component) > 0 {
c.SetComponent(component)
}
for _, o := range c.GetObjects() {
SetObjectMeta(c, o)
}
if c.HasDependencies() {
dependencies := i.GetSettings().GetParameters()
settings := c.GetDependencies()
settings = parameters.MergeSettings(dependencies, settings)
}
}
func MergeSettings(dependencies, settings *parameters.Settings) *parameters.Settings {
params := parameters.Parameters{}
if settings == nil {
settings = dependencies
} else {
settings.SetConfigRefs(append(settings.GetConfigRefs(), dependencies.GetConfigRefs()...))
settings.SetSecretRefs(append(settings.GetSecretRefs(), dependencies.GetSecretRefs()...))
for _, p := range *dependencies.GetParameters() {
params = append(params, p)
settings.Parameters = &params
}
meta.SetObjectMeta(c, o)
}
return settings
}
/*
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 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
distributed under the License is distributed on an "AS IS" BASIS,
......@@ -23,6 +23,7 @@ import (
networkingv1beta1 "k8s.io/api/networking/v1beta1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.libre.sh/interfaces"
meta "k8s.libre.sh/meta"
ingress "k8s.libre.sh/objects/ingress"
service "k8s.libre.sh/objects/service"
......@@ -30,66 +31,88 @@ import (
// +kubebuilder:object:generate=true
type Network struct {
*meta.ObjectMeta `json:"commonMeta,omitempty"`
Service Service `json:"service,omitempty"`
Ingress Ingress `json:"ingress,omitempty"`
IngressMeta *meta.ObjectMeta `json:"ingressMeta,omitempty"`
ServiceMeta *meta.ObjectMeta `json:"serviceMeta,omitempty"`
*Backend `json:",inline"`
}
// +kubebuilder:object:generate=true
type Service struct {
*meta.ObjectMeta `json:"meta,omitempty"`
Port service.Port `json:"port,omitempty"`
Type corev1.ServiceType `json:"type,omitempty"`
*Backend `json:"backend,omitempty"`
}
func (s *Service) Mutate(obj interfaces.Object) error {
service.MutateService(s, obj.(*corev1.Service), s.ObjectMeta)
meta.MutateMeta(s, obj)
return nil
}
func (s *Service) GetObject() interfaces.Object {
return &corev1.Service{}
}
// +kubebuilder:object:generate=true
type Ingress struct {
*meta.ObjectMeta `json:"meta,omitempty"`
Host string `json:"host,omitempty"`
Paths []string `json:"routes,omitempty"`
TLS bool `json:"tls,omitempty"`
TLSSecretRef string `json:"tlsSecretRef,omitempty"`
*meta.ObjectMeta `json:"commonMeta,omitempty"`
Backends []Backend `json:"backends,omitempty"`
}
func (r *Network) GetIngress() *ingress.Ingress {
ing := &ingress.Ingress{
ObjectMeta: r.Ingress.ObjectMeta,
IngressSpec: &networkingv1beta1.IngressSpec{
Rules: r.GetIngressRules(),
TLS: r.GetIngressTLS(),
},
}
return ing
// +kubebuilder:object:generate=true
type Backend struct {
ServiceName string `json:"name,omitempty"`
Hostname string `json:"hostname,omitempty"`
Paths []string `json:"routes,omitempty"`
TLS bool `json:"tls,omitempty"`
TLSSecretRef string `json:"tlsSecretRef,omitempty"`
Port service.Port `json:"port,omitempty"`
ServiceType corev1.ServiceType `json:"type,omitempty"`
}
func (c *Network) GetService() *service.Service {
svc := &service.Service{
ObjectMeta: c.Service.ObjectMeta,
ServiceSpec: &service.ServiceSpec{
Ports: []service.Port{
c.Service.Port,
},
Type: c.Service.Type,
},
}
func (i *Ingress) Mutate(obj interfaces.Object) error {
ingress.MutateIngress(i, obj.(*networkingv1beta1.Ingress))
meta.MutateMeta(i, obj)
return nil
}
return svc
func (i *Ingress) GetObject() interfaces.Object {
return &networkingv1beta1.Ingress{}
}
func (r *Network) GetIngressAnnotations() map[string]string {
return r.Ingress.ObjectMeta.Annotations
func (b *Backend) GetServiceType() corev1.ServiceType { return b.ServiceType }
func (b *Backend) GetServicePorts() []corev1.ServicePort {
ports := []corev1.ServicePort{}
ports = append(ports, b.GetServicePort())
return ports
}
func (b *Backend) GetServicePort() corev1.ServicePort {
port := corev1.ServicePort{
TargetPort: intstr.FromString(b.Port.Name),
Port: b.Port.Port,
Name: b.Port.Name,
}
if len(b.Port.Protocol) > 0 {
port.Protocol = b.Port.Protocol
}
return port
}
func (r *Network) GetIngressBackendPaths() []networkingv1beta1.HTTPIngressPath {
func (b *Backend) GetIngressBackendPaths() []networkingv1beta1.HTTPIngressPath {
bkpaths := []networkingv1beta1.HTTPIngressPath{}
for _, p := range r.Ingress.Paths {
for _, p := range b.Paths {
path := networkingv1beta1.HTTPIngressPath{
Path: p,
Backend: networkingv1beta1.IngressBackend{
ServiceName: r.Service.ObjectMeta.Name,
ServicePort: intstr.FromString(r.Service.Port.Name),
// TODO TO FIX
ServiceName: b.ServiceName,
ServicePort: intstr.FromString(b.Port.Name),
},
}
......@@ -98,40 +121,54 @@ func (r *Network) GetIngressBackendPaths() []networkingv1beta1.HTTPIngressPath {
return bkpaths
}
func (r *Network) GetIngressRules() []networkingv1beta1.IngressRule {
rules := []networkingv1beta1.IngressRule{}
func (b *Backend) GetIngressRule() networkingv1beta1.IngressRule {
rule := networkingv1beta1.IngressRule{
Host: r.Ingress.Host,
Host: b.Hostname,
IngressRuleValue: networkingv1beta1.IngressRuleValue{
HTTP: &networkingv1beta1.HTTPIngressRuleValue{
Paths: r.GetIngressBackendPaths(),
Paths: b.GetIngressBackendPaths(),
},
},
}
rules = append(rules, rule)
return rule
}
func (i *Ingress) GetIngressRules() []networkingv1beta1.IngressRule {
rules := []networkingv1beta1.IngressRule{}
for _, ing := range i.Backends {
rules = append(rules, ing.GetIngressRule())
}
return rules
}
func (r *Network) GetIngressTLS() []networkingv1beta1.IngressTLS {
func (b *Backend) GetIngressTLS() networkingv1beta1.IngressTLS {
tls := networkingv1beta1.IngressTLS{}
tlsList := []networkingv1beta1.IngressTLS{}
if &r.Ingress.TLS != nil {
if len(r.Ingress.TLSSecretRef) == 0 {
r.Ingress.TLSSecretRef = fmt.Sprintf("%v-%v", strings.Replace(r.Ingress.Host, ".", "-", -1), "tls")
if b.TLS {
if len(b.TLSSecretRef) == 0 {
b.TLSSecretRef = fmt.Sprintf("%v-%v", strings.Replace(b.Hostname, ".", "-", -1), "tls")
}
tls = networkingv1beta1.IngressTLS{
SecretName: r.Ingress.TLSSecretRef,
SecretName: b.TLSSecretRef,
}
tls.Hosts = append(tls.Hosts, r.Ingress.Host)
tlsList = append(tlsList, tls)
} else {
tlsList = nil
tls.Hosts = append(tls.Hosts, b.Hostname)
}
return tls
}
func (i *Ingress) GetIngressTLS() []networkingv1beta1.IngressTLS {
tlsList := []networkingv1beta1.IngressTLS{}
for _, ing := range i.Backends {
tlsList = append(tlsList, ing.GetIngressTLS())
}
return tlsList
}
/*
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 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
distributed under the License is distributed on an "AS IS" BASIS,
......@@ -16,16 +16,19 @@ limitations under the License.
package components
import (
instance "k8s.libre.sh/instance"
settings "k8s.libre.sh/application/settings"
meta "k8s.libre.sh/meta"
"k8s.libre.sh/objects"
deployment "k8s.libre.sh/objects/deployment"
parameters "k8s.libre.sh/settings"
corev1 "k8s.io/api/core/v1"
)
const DefaultComponent string = "app"
// +kubebuilder:object:generate=true
type Workload struct {
*meta.ObjectMeta `json:"commonMeta,omitempty"`
//*Settings `json:"settings,omitempty"`
*meta.ObjectMeta `json:"commonMeta,omitempty"`
*deployment.Deployment `json:"deployment,omitempty"`
*Network `json:"network,omitempty"`
Dependencies bool `json:"dependencies,omitempty"`
......@@ -35,59 +38,91 @@ func (w *Workload) HasDependencies() bool {
return w.Dependencies
}
func (w *Workload) GetMeta() instance.Meta {
func (w *Workload) GetMeta() meta.Instance {
return w.ObjectMeta
}
func (w *Workload) GetObjects() map[int]instance.Object {
func (w *Workload) GetObjects() map[int]objects.Object {
objects := make(map[int]instance.Object)
objects := make(map[int]objects.Object)
objects[0] = w.Network.GetService()
objects[1] = w.Network.GetIngress()
ing := &Ingress{
// TODO TO FIX
ObjectMeta: w.IngressMeta,
Backends: []Backend{
*w.Backend,
},
}
srv := &Service{
// TODO TO FIX
ObjectMeta: w.ServiceMeta,
Backend: w.Backend,
}
meta.SetObjectMeta(w.ObjectMeta, ing.ObjectMeta)
meta.SetObjectMeta(w.ObjectMeta, srv.ObjectMeta)
objects[0] = srv
objects[1] = ing
objects[2] = w.Deployment
return objects
}
func (w *Workload) SetDependencies(s *parameters.Settings) { w.Settings = *s }
func (w *Workload) GetDependencies() parameters.Interface { return &w.Settings }
func (w *Workload) SetDependencies(s *settings.Component) { w.ConfigSpec = s.ConfigSpec }
func (w *Workload) GetDependencies() settings.Config { return w.ConfigSpec }
// TODO make a generic function with component interface
// getObjects loop setObjectMetaFromComponent
// merge labels && annotations && finalizers not set
func (w *Workload) SetDefaults(i instance.Instance) {
func (w *Workload) SetDefaults() {
// TODO FIXME
w.Dependencies = true
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() {
// TODO improve initialisation of objectMeta, labels...
if w.ObjectMeta == nil {
w.ObjectMeta = new(meta.ObjectMeta)
w.ObjectMeta = &meta.ObjectMeta{}
}
if len(w.ObjectMeta.Labels) == 0 {
w.ObjectMeta.Labels = make(map[string]string)
}
// TODO TOFIX
w.ObjectMeta.SetComponent("app")
// TODO FIXME
if len(w.ObjectMeta.GetComponent()) == 0 {
w.ObjectMeta.SetComponent(DefaultComponent)
}
if w.Deployment.ObjectMeta == nil {
w.Deployment.ObjectMeta = new(meta.ObjectMeta)
w.Deployment.ObjectMeta = &meta.ObjectMeta{}
}
if w.Network.ObjectMeta == nil {
w.Network.ObjectMeta = new(meta.ObjectMeta)
if w.ConfigSpec == nil {
w.ConfigSpec = &settings.ConfigSpec{}
}
if w.Network.Ingress.ObjectMeta == nil {
w.Network.Ingress.ObjectMeta = new(meta.ObjectMeta)
if w.Backend == nil {
w.Backend = &Backend{}
}
if w.Network.Service.ObjectMeta == nil {
w.Network.Service.ObjectMeta = new(meta.ObjectMeta)
if w.ServiceMeta == nil {
w.ServiceMeta = &meta.ObjectMeta{}
}
instance.InitComponent(i, w)
if w.IngressMeta == nil {
w.IngressMeta = &meta.ObjectMeta{}
}
}
......@@ -25,26 +25,22 @@ import (
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Ingress) DeepCopyInto(out *Ingress) {
func (in *Backend) DeepCopyInto(out *Backend) {
*out = *in
if in.ObjectMeta != nil {
in, out := &in.ObjectMeta, &out.ObjectMeta
*out = new(meta.ObjectMeta)
(*in).DeepCopyInto(*out)
}
if in.Paths != nil {
in, out := &in.Paths, &out.Paths
*out = make([]string, len(*in))
copy(*out, *in)
}
out.Port = in.Port
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Ingress.
func (in *Ingress) DeepCopy() *Ingress {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backend.
func (in *Backend) DeepCopy() *Backend {
if in == nil {
return nil
}
out := new(Ingress)
out := new(Backend)
in.DeepCopyInto(out)
return out
}
......@@ -52,42 +48,29 @@ func (in *Ingress) DeepCopy() *Ingress {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Network) DeepCopyInto(out *Network) {
*out = *in
if in.ObjectMeta != nil {
in, out := &in.ObjectMeta, &out.ObjectMeta
if in.IngressMeta != nil {
in, out := &in.IngressMeta, &out.IngressMeta
*out = new(meta.ObjectMeta)
(*in).DeepCopyInto(*out)
}
in.Service.DeepCopyInto(&out.Service)
in.Ingress.DeepCopyInto(&out.Ingress)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Network.
func (in *Network) DeepCopy() *Network {
if in == nil {
return nil
}
out := new(Network)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Service) DeepCopyInto(out *Service) {
*out = *in
if in.ObjectMeta != nil {
in, out := &in.ObjectMeta, &out.ObjectMeta
if in.ServiceMeta != nil {
in, out := &in.ServiceMeta, &out.ServiceMeta
*out = new(meta.ObjectMeta)
(*in).DeepCopyInto(*out)
}
out.Port = in.Port
if in.Backend != nil {
in, out := &in.Backend, &out.Backend
*out = new(Backend)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Service.
func (in *Service) DeepCopy() *Service {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Network.
func (in *Network) DeepCopy() *Network {
if in == nil {
return nil
}
out := new(Service)
out := new(Network)
in.DeepCopyInto(out)
return out
}
......
/*
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
import (
"context"
"github.com/presslabs/controller-util/syncer"
settings "k8s.libre.sh/application/settings"
"k8s.libre.sh/interfaces"
"k8s.libre.sh/meta"
"k8s.libre.sh/objects"
)
type Instance interface {
meta.Instance
GetComponents() map[int]Component
GetOwner() interfaces.Object
GetSettings() settings.Settings
// GetSettings() map[int]settings.Settings
SetDefaults()
}
func Init(i Instance) {
i.SetDefaults()
for _, c := range i.GetComponents() {
c.Init()
// TODO TOFIX
component := c.GetComponent()
meta.SetObjectMeta(i, c)
if len(component) > 0 {
c.SetComponent(component)
}
for _, o := range c.GetObjects() {
meta.SetObjectMeta(c, o)
}
c.SetDefaults()
}
}
func NewSyncers(app Instance, r interfaces.Reconcile, owner interfaces.Object) (syncers []syncer.Interface, err error) {
////////////////////
//// Settings //////
///////////////////
// TODO TO FIX SHOULD BE RUN IN INITIALIZED FUNCTION
// INITIALISE VALUES FROM EXTERNAL RESOURCES, RANDOM & TEMPLATES
// sett := app.GetSettings().GetConfig().(*components.Settings)
sett := app.GetSettings().(*settings.Component)
err = sett.Init(r.GetClient())
if err != nil {
return syncers, err
}
// Object Syncers
for _, obj := range sett.GetObjects() {
// meta.SetObjectMeta(sett.CommonMeta, obj)
s := objects.NewObjectSyncer(obj, owner, r)
if err := syncer.Sync(context.TODO(), s, r.GetRecorder()); err != nil {
return syncers, err
}
}
/////////////////////
//// Components ////
///////////////////
components := app.GetComponents()
// TODO TO FIX SHOULD BE RUN IN INITIALIZED FUNCTION
// INITIALIZE
for _, c := range components {
if c.HasDependencies() {
deps := c.GetDependencies()
deps = settings.MergeSettings(sett, deps)
}
// GET SYNCERS
mutators := c.GetObjects()
for _, m := range mutators {
syncers = append(syncers, objects.NewObjectSyncer(m, owner, r))
}
}
return syncers, nil
}
/*
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 settings
import (
"strings"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"k8s.libre.sh/application/settings/parameters"
"k8s.libre.sh/meta"
"k8s.libre.sh/objects"
"k8s.libre.sh/objects/configmap"
"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
type SettingsSpec struct {
Sources []Source `json:"sources,omitempty"`
// Parameters is a list of parameters
*parameters.Parameters `json:"parameters,omitempty"`
}
type CreateOptions 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"`
}
func (s *Component) GetConfig() Config { return s.ConfigSpec }
func (s *Component) GetMeta() meta.Instance { return s.CommonMeta }
func (s *Component) GetSecretMeta() meta.Instance { return s.SecretMeta }
func (s *Component) GetConfigMapMeta() meta.Instance { return s.ConfigMeta }
func (s *Component) SetDefaults() {
// TODO TO FIX DUPLICATE WITH INIT
meta.SetObjectMeta(s.CommonMeta, s.SecretMeta)
meta.SetObjectMeta(s.CommonMeta, s.ConfigMeta)
}
func (s *Component) GetObjects() map[int]objects.Object {
cm := &configmap.ConfigMap{
ObjectMeta: s.ConfigMeta,
}
secret := &secret.Secret{
ObjectMeta: s.SecretMeta,
}
objs := make(map[int]objects.Object, 2)
genConfigParams := []string{}
genSecretParams := []string{}
for _, p := range *s.ConfigSpec.Parameters {
// TODO TO FIX
if p.MountType == parameters.MountEnvFile &&
// TODO TO FIX
(p.Type == parameters.SecretParameter || p.Type == "") &&
len(p.Value) > 0 {
if p.Generate != parameters.GenerateTemplate && p.Generate != "" {
genSecretParams = append(genSecretParams, p.Key)
}
secret.Parameters = append(secret.Parameters, p)
}
if p.MountType == parameters.MountEnvFile &&
p.Type == parameters.ConfigParameter &&
len(p.Value) > 0 {
if p.Generate != parameters.GenerateTemplate && p.Generate != "" {
genConfigParams = append(genConfigParams, p.Key)
}
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
if len(cm.Parameters) > 0 {
objs[0] = cm
}
if len(secret.Parameters) > 0 {
if objs[0] == nil {
objs[0] = secret
} else {
objs[1] = secret
}
}
return objs
}
func (s *Component) Init(c client.Client) error {
// TODO TO FIX DUPLICATE WITH SETDEFAULTS
meta.SetObjectMeta(s.CommonMeta, s.ConfigMeta)
meta.SetObjectMeta(s.CommonMeta, s.SecretMeta)
err := InitParametersValueFrom(s, c)
if err != nil {
return err
}
s.InitRandValues()
err = s.InitTemplateValues(parameters.KeyPairValues(s.Parameters))
if err != nil {
return err
}
return nil
}
// InitParametersValueFrom intialise the parameters with values provided in external resources in the same namespace
// All parameters values are filled from those resources
// Only Secrets and Configmaps are supported
func InitParametersValueFrom(s *Component, c client.Client) error {
params := parameters.Parameters{}
paramsByKey := parameters.ParametersByKey(s.Parameters)
paramsBySecretSource, paramsByConfigMapSource := OrderByResourceRef(s.ConfigSpec)
cm := &corev1.ConfigMap{}
sec := &corev1.Secret{}
cm.SetNamespace(s.CommonMeta.GetNamespace())
sec.SetNamespace(s.CommonMeta.GetNamespace())
for k, v := range paramsBySecretSource {
sec.SetName(k)
err := parameters.GetAndMergeParameters(v, paramsByKey, c, sec)
if err != nil {
return err
}
}
for k, v := range paramsByConfigMapSource {
cm.SetName(k)
err := parameters.GetAndMergeParameters(v, paramsByKey, c, cm)
if err != nil {
return err
}
}
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 {
if v.MountType == parameters.MountEnvFile {
v.Ref = ""
if !addConfigSrc && v.Type == parameters.ConfigParameter {
s.Sources = append(s.Sources, configSrc)
addConfigSrc = true
} else if !addSecretSrc && v.Type == parameters.SecretParameter {
s.Sources = append(s.Sources, secretSrc)
addSecretSrc = true
}
}
params = append(params, v)
}
s.Parameters = &params
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 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 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
import (
"sort"
corev1 "k8s.io/api/core/v1"
"k8s.libre.sh/application/settings/parameters"
)
// +kubebuilder:object:generate=true
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
type ConfigSpec struct {
// Sources is a list of sources for the parameters from kubernetes resources in the same namespace
Sources []Source `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 {
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 }
// GetEnvFrom returns a list of EnvFromSource to populate environment variables in the container.
func (c *ConfigSpec) GetEnvFrom() []corev1.EnvFromSource {
// envFroms := []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),
}
c.Sources = append(c.Sources, src)
}
}
}
if len(c.Sources) > 0 {
for _, source := range c.Sources {
if source.Type == "configmap" {
envFrom = corev1.EnvFromSource{
ConfigMapRef: &corev1.ConfigMapEnvSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: source.Ref,
},
},
}
// envFromMap[k] = envFrom
envFromConfigMap = append(envFromConfigMap, envFrom)
} else if source.Type == "secret" {
envFrom = corev1.EnvFromSource{
SecretRef: &corev1.SecretEnvSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: source.Ref,
},
},
}
// 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 {
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
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) {
*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 ConfigSpec.
func (in *ConfigSpec) DeepCopy() *ConfigSpec {
if in == nil {
return nil
}
out := new(ConfigSpec)
in.DeepCopyInto(out)
return out
}
/*
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 settings
import (
"k8s.libre.sh/application/settings/parameters"
)
type Config interface {
GetParameters() *parameters.Parameters
SetParameters(*parameters.Parameters)
InitRandValues()
InitTemplateValues(map[string]string) error
// InitExternaValues(c client.Client) error
SetSources(sources []Source)
GetSources() (sources []Source)
}
func MergeSettings(src, dest Config) Config {
if dest == nil {
dest = src
} else {
dest.SetSources(append(dest.GetSources(), src.GetSources()...))
params := *dest.GetParameters()
if params == nil {
params = *src.GetParameters()
} else {
for _, p := range *src.GetParameters() {
params = append(params, p)
}
}
dest.SetParameters(&params)
}
return dest
}
/*
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 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
distributed under the License is distributed on an "AS IS" BASIS,
......@@ -13,28 +13,39 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package settings
package parameters
const (
GenerateRand Generate = "rand"
GenerateRand12 Generate = "rand12"
GenerateRand24 Generate = "rand24"
// Random value
GenerateRand Generate = "rand"
// Random value of size 12
GenerateRand12 Generate = "rand12"
// Random value of size 24
GenerateRand24 Generate = "rand24"
// Value is generated from a template
// Value container the template and will be replaced
GenerateTemplate Generate = "template"
)
const (
// Parameter is mounted as key/value in the container envVar specs
MountLiteral MountType = "literal"
MountFrom MountType = "from"
MountFile MountType = "file"
// MountEnvVar MountType = "envVar"
// MountEnvVarFrom MountType = "envVarFrom"
// Parameter is mounted as as EnvVarSource in the container envVar specs
// no data is transformed in a new resource
MountFrom MountType = "from"
// Parameter is mouned as file in the container path
MountFile MountType = "file"
// Parameter is mounted as EnvFromSource in the container specs
// Data can be retrieved from the crds or external resources specified in the parameter envFrom
// and transformed in a new secret or configmap
MountEnvFile MountType = "envFile"
)
const (
ConfigParameter ParameterType = "configmap"
SecretParameter ParameterType = "secret"
ObjectFieldParameter ParameterType = "field"
TemplateValue ParameterType = "templateValue"
)
type MountType string
......@@ -46,41 +57,39 @@ type Parameters []*Parameter
// +kubebuilder:object:generate=true
type Parameter struct {
// Key that will be mounted as environment variable
// Key of the parameter, can be mounted as as an environment variable, used in template
// or as in the data fied of configmap/secret
//
// Key must be unique
Key string `json:"key,omitempty"`
// Value of the paramater, should not contain secret values
// If it is a template, ParameterType should be template
Value string `json:"value,omitempty"`
// ValueFrom specifies where to get the value from for the parameter
// ValueFrom when specified indicates the source of the parameter.
// Cannot be used if value is not empty.
ValueFrom `json:",inline"`
// MountFrom specifies where the parameter will be mounted as file
// MountPath specifies where the parameter will be mounted as a file
MountPath MountPath `json:"mountFrom,omitempty"`
// Generate is specified if a secret or configmap data needs to be randomly generated
// Generate if specified defines how the parameter value will be generated
Generate Generate `json:"generate,omitempty"`
// Type specifies if its a ConfigMap or Secret
Type ParameterType `json:"type,omitempty"`
MountType MountType `json:"mountType,omitempty"`
// Type specifies specifies the parameter type
Type ParameterType `json:"type,omitempty"`
// MountType defined how the parameter will be mounted in the pod
// Defaults to EnvFile
MountType MountType `json:"mountType,omitempty"`
}
type ValueFrom struct {
// Key to select from in ConfigMap or Secret
// Key to select from the source
FromKey string `json:"fromKey,omitempty"`
// Ref is a reference to a local object, set ParameterType to define the object
// Name of the referent.
Ref string `json:"ref,omitempty"`
// Type of the parameter's source
// Defaults to the parameter type if not specified
RefType ParameterType `json:"refType,omitempty"`
}
type MountPath struct {
Path string `json:"path,omitempty"`
SubPath string `json:"subPath,omitempty"`
}
// +kubebuilder:object:generate=true
type SecretParam struct {
// Key that will be mounted as environment variable
Key string `json:"key,omitempty"`
// ValueFrom specifies where to get the value from for the parameter
ValueFrom `json:",inline"`
// Source of the Secret or ConfigMap
Destination string `json:"destination,omitempty"`
// Source of the Secret or ConfigMap
Generate bool `json:"generate,omitempty"`
}
/*
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 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
distributed under the License is distributed on an "AS IS" BASIS,
......@@ -13,7 +13,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package settings
package parameters
import (
"errors"
......@@ -21,8 +21,8 @@ import (
corev1 "k8s.io/api/core/v1"
)
// GetEnvVar gets an environment variables to set in the container.
func (p *Parameter) GetEnvVar() (envVar corev1.EnvVar, err error) {
switch p.MountType {
case MountLiteral:
if len(p.Value) > 0 && len(p.Key) > 0 {
......@@ -50,6 +50,7 @@ func (p *Parameter) GetEnvVar() (envVar corev1.EnvVar, err error) {
},
}
return envVar, nil
case ConfigParameter:
envVar = corev1.EnvVar{
Name: p.Key,
......@@ -63,6 +64,7 @@ func (p *Parameter) GetEnvVar() (envVar corev1.EnvVar, err error) {
},
}
return envVar, nil
case ObjectFieldParameter:
envVar = corev1.EnvVar{
Name: p.Key,
......@@ -77,6 +79,7 @@ func (p *Parameter) GetEnvVar() (envVar corev1.EnvVar, err error) {
}
}
return envVar, errors.New("missing arguments")
default:
return envVar, errors.New("wrong MountType")
}
......
/*
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 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
distributed under the License is distributed on an "AS IS" BASIS,
......@@ -13,11 +13,11 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package settings
package parameters
import (
"bytes"
"reflect"
"sort"
"text/template"
"github.com/presslabs/controller-util/rand"
......@@ -26,9 +26,10 @@ import (
func (p *Parameters) InitValues() {
p.InitRandValues()
p.InitTemplateValues(p.KeyPairValues())
p.InitTemplateValues(KeyPairValues(p))
}
// InitRandValues initialies the parameters random values
func (p *Parameters) InitRandValues() {
for _, param := range *p {
......@@ -53,91 +54,42 @@ func (p *Parameters) InitRandValues() {
}
}
func (p *Parameters) InitTemplateValues(values map[string]string) {
// InitTemplateValues initialies the parameters values from a template and a key pair value set
// The template shoud be in the parameter value when GenerateTemplate is specified and the values
// will be replaced from the result of the template processing.
func (p *Parameters) InitTemplateValues(values map[string]string) error {
for _, param := range *p {
if param.Generate == GenerateTemplate {
tmpl, err := template.New(param.Key).Parse(param.Value)
if err != nil {
// return nil, err
return err
}
var tpl bytes.Buffer
err = tmpl.Execute(&tpl, values)
if err != nil {
// return nil, err
return err
}
param.Value = tpl.String()
}
}
return nil
}
func (p *Parameters) SortByMountType() map[MountType]Parameters {
data := make(map[MountType]Parameters)
for _, param := range *p {
data[param.MountType] = append(data[param.MountType], param)
}
return data
}
func (p *Parameters) KeyPairValues() map[string]string {
data := make(map[string]string)
sorted := p.SortByMountType()
for _, param := range sorted[MountLiteral] {
if len(param.Value) > 0 && len(param.Key) > 0 {
data[param.Key] = param.Value
}
}
for _, param := range sorted[MountFrom] {
if len(param.Value) > 0 && len(param.Key) > 0 {
data[param.Key] = param.Value
}
}
return data
}
// GetData get the data for the secret or configmap as a key:values
// This function only returns data which should be either in a secret or a configmap
// It implements the configmap and secret interfaces
func (p *Parameters) GetData() map[string]string {
data := make(map[string]string)
for _, param := range *p {
if param.MountType == MountFrom && param.Type != ObjectFieldParameter && len(param.Value) > 0 {
data[param.Key] = param.Value
}
}
return data
}
func (p *Parameters) GetSecretData() map[string]string {
data := make(map[string]string)
for _, param := range *p {
if param.MountType == MountFrom && param.Type == SecretParameter {
data[param.Key] = param.Value
}
}
return data
}
func (p *Parameters) GetConfigData() map[string]string {
data := make(map[string]string)
for _, param := range *p {
if param.MountType == MountFrom &&
param.Type == ConfigParameter &&
// TODO TO FIX
if (param.MountType == MountEnvFile || param.MountType == "") &&
param.Type != ObjectFieldParameter &&
len(param.Value) > 0 {
data[param.Key] = param.Value
}
......@@ -146,7 +98,8 @@ func (p *Parameters) GetConfigData() map[string]string {
return data
}
func (p *Parameters) GetEnv() []corev1.EnvVar {
// GetEnvVar gets a list of environment variables to set in the container.
func (p *Parameters) GetEnvVar() []corev1.EnvVar {
envVars := []corev1.EnvVar{}
envVar := corev1.EnvVar{}
......@@ -154,7 +107,7 @@ func (p *Parameters) GetEnv() []corev1.EnvVar {
for _, param := range *p {
envVar, err = param.GetEnvVar()
// TODO TOFIX
if err != nil {
}
......@@ -163,41 +116,13 @@ func (p *Parameters) GetEnv() []corev1.EnvVar {
}
}
// TODO IMPROVE
if len(envVars) > 0 {
// 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 envVars[i].Name < envVars[j].Name
})
return envVars
}
return nil
}
func Marshal(i interface{}) (Parameters, error) {
parameters := Parameters{}
t := reflect.TypeOf(i)
ifv := reflect.ValueOf(i)
for ii := 0; ii < t.NumField(); ii++ {
f := t.Field(ii)
fv := ifv.Field(ii)
parameter, ok := fv.Interface().(Parameter)
if !ok {
// return nil, ok
}
env, ok := f.Tag.Lookup("env")
if !ok {
// return nil, ok
}
if len(parameter.Key) == 0 {
parameter.Key = env
}
parameters = append(parameters, &parameter)
}
return parameters, nil
}
package settings_test
package parameters_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "k8s.libre.sh/settings"
. "k8s.libre.sh/application/settings/parameters"
corev1 "k8s.io/api/core/v1"
)
......@@ -24,8 +24,8 @@ var _ = Describe("Parameters", func() {
valueFromSecret ValueFrom
valueFromObject ValueFrom
parameters *Parameters
settings *Settings
envFrom *EnvFrom
// settings *Settings
// envFrom *EnvFrom
)
BeforeEach(func() {
......@@ -43,7 +43,7 @@ var _ = Describe("Parameters", func() {
Value: "{{ .LITERAL_PARAMETER }}",
Type: ConfigParameter,
Generate: GenerateTemplate,
MountType: MountFrom,
MountType: MountEnvFile,
}
paramEnvVar = Parameter{
......@@ -82,24 +82,6 @@ var _ = Describe("Parameters", func() {
MountType: MountFrom,
}
// TODO THIS SHOULD THROW AN ERROR
// paramEnvFrom = Parameter{
// ValueFrom: ValueFrom{
// Ref: "confgRef",
// },
// Type: ConfigParameter,
// MountType: MountFrom,
// }
// paramEnvFromSecret = Parameter{
// ValueFrom: ValueFrom{
// Ref: "secretRef",
// },
// Type: SecretParameter,
// MountType: MountFrom,
// }
paramEnvVarFromObject = Parameter{
Key: "PARAMETER_FROM_OBJECT",
Type: ObjectFieldParameter,
......@@ -130,20 +112,20 @@ var _ = Describe("Parameters", func() {
&paramMountFile,
}
envFrom = &EnvFrom{
SecretRefs: []string{
"mysecret",
"myothersecret",
},
ConfigRefs: []string{
"myconfigmap",
},
}
settings = &Settings{
EnvFrom: envFrom,
Parameters: parameters,
}
/* envFrom = &EnvFrom{
SecretRefs: []string{
"mysecret",
"myothersecret",
},
ConfigRefs: []string{
"myconfigmap",
},
}
settings = &Settings{
EnvFrom: envFrom,
Parameters: parameters,
} */
})
......@@ -207,7 +189,7 @@ var _ = Describe("Parameters", func() {
})
})
Describe("Generating Env for containers with EnvFrom", func() {
/* Describe("Generating Env for containers with EnvFrom", func() {
Context("Generating env", func() {
It("should generate envFrom", func() {
......@@ -241,74 +223,78 @@ var _ = Describe("Parameters", func() {
// Expect(err).NotTo(HaveOccurred())
})
})
Describe("Generating Env for containers with Parameters", func() {
Context("Generating envFrom", func() {
It("should generate envVar", func() {
expectedObj := []corev1.EnvVar{
{
Name: "LITERAL_PARAMETER",
Value: "LiteralParameter",
},
{
Name: "VALUE_FROM_CONFIG_PARAMETER",
ValueFrom: &corev1.EnvVarSource{
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: "configRef",
},
Key: "FROM_KEY_CONFIG_PARAMETER",
}) */
Describe("Generating Env for containers with Parameters", func() {
Context("Generating envFrom", func() {
It("should generate envVar", func() {
expectedObj := []corev1.EnvVar{
{
Name: "LITERAL_PARAMETER",
Value: "LiteralParameter",
},
{
Name: "VALUE_FROM_CONFIG_PARAMETER",
ValueFrom: &corev1.EnvVarSource{
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: "configRef",
},
Key: "FROM_KEY_CONFIG_PARAMETER",
},
},
{
Name: "VALUE_FROM_SECRET_PARAMETER",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: "secretRef",
},
Key: "FROM_KEY_SECRET_PARAMETER",
},
{
Name: "VALUE_FROM_SECRET_PARAMETER",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: "secretRef",
},
Key: "FROM_KEY_SECRET_PARAMETER",
},
},
{
Name: "PARAMETER_FROM_OBJECT",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "status.podIP",
},
},
{
Name: "PARAMETER_FROM_OBJECT",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "status.podIP",
},
},
{
Name: "TEMPLATE_PARAMETER",
Value: "LiteralParameter",
},
}
},
{
Name: "TEMPLATE_PARAMETER",
Value: "LiteralParameter",
},
}
parameters.InitValues()
res := parameters.GetEnv()
parameters.InitValues()
res := parameters.GetEnvVar()
Expect(res).To(Equal(expectedObj))
// Expect(err).NotTo(HaveOccurred())
})
Expect(res).To(Equal(expectedObj))
// Expect(err).NotTo(HaveOccurred())
})
})
Describe("Generating data for configmap and secret with Parameters", func() {
Context("Generating data", func() {
It("should generate data", func() {
parameters.InitValues()
})
expectedObj := map[string]string{
"TEMPLATE_PARAMETER_FROM": "LiteralParameter",
}
Describe("Generating data for configmap and secret with Parameters", func() {
Context("Generating data", func() {
It("should generate data", func() {
parameters.InitValues()
Expect(parameters.GetConfigData()).To(Equal(expectedObj))
// Expect(err).NotTo(HaveOccurred())
})
expectedObj := map[string]string{
"TEMPLATE_PARAMETER_FROM": "LiteralParameter",
}
Expect(parameters.GetData()).To(Equal(expectedObj))
// Expect(err).NotTo(HaveOccurred())
})
})
})
/*
Describe("Generating mount files", func() {
Context("Generating volumes & volume mount", func() {
It("should generate volume for pod", func() {
......@@ -339,5 +325,6 @@ var _ = Describe("Parameters", func() {
})
})
})
})
*/
})
/*
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 parameters
import (
"context"
"errors"
"reflect"
corev1 "k8s.io/api/core/v1"
"k8s.libre.sh/interfaces"
"sigs.k8s.io/controller-runtime/pkg/client"
)
func Marshal(i interface{}) (Parameters, error) {
parameters := Parameters{}
t := reflect.TypeOf(i)
ifv := reflect.ValueOf(i)
for ii := 0; ii < t.NumField(); ii++ {
f := t.Field(ii)
fv := ifv.Field(ii)
parameter, ok := fv.Interface().(Parameter)
// TODO Return error
if !ok {
// return nil, ok
}
env, ok := f.Tag.Lookup("env")
if !ok {
// return nil, ok
}
if len(parameter.Key) == 0 {
parameter.Key = env
}
// if len(parameter.MountType) == 0 {
// parameter.MountType = MountEnvFile
// }
parameters = append(parameters, &parameter)
}
return parameters, nil
}
// Sort parameters by keys
func ParametersByKey(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
func KeyPairValues(p *Parameters) map[string]string {
data := make(map[string]string)
for _, param := range *p {
data[param.Key] = param.Value
}
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
}
......@@ -17,35 +17,10 @@ limitations under the License.
// Code generated by controller-gen. DO NOT EDIT.
package settings
package parameters
import ()
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *EnvFrom) DeepCopyInto(out *EnvFrom) {
*out = *in
if in.SecretRefs != nil {
in, out := &in.SecretRefs, &out.SecretRefs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.ConfigRefs != nil {
in, out := &in.ConfigRefs, &out.ConfigRefs
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvFrom.
func (in *EnvFrom) DeepCopy() *EnvFrom {
if in == nil {
return nil
}
out := new(EnvFrom)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Parameter) DeepCopyInto(out *Parameter) {
*out = *in
......@@ -87,19 +62,3 @@ func (in Parameters) DeepCopy() Parameters {
in.DeepCopyInto(out)
return *out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *SecretParam) DeepCopyInto(out *SecretParam) {
*out = *in
out.ValueFrom = in.ValueFrom
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretParam.
func (in *SecretParam) DeepCopy() *SecretParam {
if in == nil {
return nil
}
out := new(SecretParam)
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 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
distributed under the License is distributed on an "AS IS" BASIS,
......@@ -13,73 +13,36 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package instance
package settings
import (
meta "k8s.libre.sh/meta"
"k8s.libre.sh/objects/configmap"
secret "k8s.libre.sh/objects/secret"
parameters "k8s.libre.sh/settings"
)
"k8s.libre.sh/meta"
type Dependency interface {
GetParameters() parameters.Interface
// GetSecretParameters() *parameters.Settings
// GetConfigParameters() *parameters.Settings
SetDefaults(i Instance)
}
"sigs.k8s.io/controller-runtime/pkg/client"
)
type Settings interface {
GetMeta() Meta
GetSecretMeta() Meta
GetConfigMapMeta() Meta
GetParameters() parameters.Interface
// GetSecretParameters() *parameters.Settings
// GetConfigParameters() *parameters.Settings
// GetSecret() secret.Mutate
// GetConfigMap() configmap.Mutate
SetDefaults(i Instance)
GetMeta() meta.Instance
GetSecretMeta() meta.Instance
GetConfigMapMeta() meta.Instance
GetConfig() Config
SetDefaults()
Init(c client.Client) error
}
func InitParametersFromSettings(s Settings, p parameters.Interface) {
secretRefs := p.GetSecretRefs()
configRefs := p.GetConfigRefs()
for _, param := range *p.GetParameters() {
if len(param.MountType) == 0 {
param.MountType = parameters.MountFrom
if len(param.ValueFrom.Ref) == 0 {
if param.Type == parameters.SecretParameter {
secretRefs = append(secretRefs, s.GetMeta().GetName())
}
configRefs = append(configRefs, s.GetMeta().GetName())
}
}
if len(param.Type) == 0 {
param.Type = parameters.ConfigParameter
}
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(),
},
}
p.SetConfigRefs(Unique(configRefs))
p.SetSecretRefs(Unique(secretRefs))
}
func Unique(stringSlice []string) []string {
keys := make(map[string]bool)
list := []string{}
for _, entry := range stringSlice {
if _, value := keys[entry]; !value {
keys[entry] = true
list = append(list, entry)
}
}
return list
}
func GetObjects(s Settings) map[int]Object {
/* func GetObjects(s Settings) map[int]objects.Object {
cm := &configmap.ConfigMap{
ObjectMeta: &meta.ObjectMeta{},
......@@ -89,32 +52,33 @@ func GetObjects(s Settings) map[int]Object {
ObjectMeta: &meta.ObjectMeta{},
}
objs := make(map[int]Object, 2)
objs := make(map[int]objects.Object, 2)
SetObjectMeta(s.GetMeta(), cm.ObjectMeta)
SetObjectMeta(s.GetMeta(), secret.ObjectMeta)
meta.SetObjectMeta(s.GetConfigMapMeta(), cm.ObjectMeta)
meta.SetObjectMeta(s.GetSecretMeta(), secret.ObjectMeta)
// TODO REPLACE BY GET SECRET PARAMETERS & GET CONFIG PARAMETERS
params := s.GetParameters()
params := s.GetConfig()
for _, p := range *params.GetParameters() {
// TODO check not mountLiteral ??
if p.Type == parameters.SecretParameter && len(p.Value) > 0 {
if p.MountType == parameters.MountEnvFile &&
// TO FIX
p.Type == parameters.SecretParameter &&
len(p.Value) > 0 {
secret.Parameters = append(secret.Parameters, p)
}
if p.Type == parameters.ConfigParameter && len(p.Value) > 0 {
if p.MountType == parameters.MountEnvFile &&
p.Type == parameters.ConfigParameter &&
len(p.Value) > 0 {
cm.Parameters = append(cm.Parameters, p)
}
}
// TODO IMPROVE
if len(cm.Parameters) > 0 {
// cm.Parameters = cmParameters
objs[0] = cm
}
if len(secret.Parameters) > 0 {
// secret.Parameters = secretParameters
if objs[0] == nil {
objs[0] = secret
......@@ -125,3 +89,4 @@ func GetObjects(s Settings) map[int]Object {
return objs
}
*/
/*
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 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{}
}
}
// 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)
}
}
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
}
package components
/*
// +kubebuilder:object:generate=true
type Settings struct {
*meta.ObjectMeta `json:"meta,omitempty"`
parameters.Parameters `json:"parameters,omitempty"`
}
func (s *Settings) GetParameters() *parameters.Parameters {
return &s.Parameters
}
func (s *Settings) GetObjects() []instance.Object {
objects := []instance.Object{}
// for _, param := range *s.Parameters {
// if len(param.Value) > 0 && len(param.Key) > 0 {
// if param.Type == "Secret" {
// objects = append(objects, secret)
// }
// objects = append(objects, secret)
// }
// }
return objects
}
func (s *Settings) GetConfigRefs() []string { return nil }
func (s *Settings) GetSecretRefs() []string { return nil }
func (s *Settings) SetDefaults(i instance.Instance) {
if s.ObjectMeta == nil {
s.ObjectMeta = new(meta.ObjectMeta)
}
if len(s.ObjectMeta.Labels) == 0 {
s.ObjectMeta.Labels = make(map[string]string)
}
instanceLabels := instance.InstanceLabels(i)
s.ObjectMeta.SetLabels(instanceLabels)
s.ObjectMeta.Labels["app.kubernetes.io/component"] = "settings"
if len(s.ObjectMeta.Name) == 0 {
s.ObjectMeta.Name = fmt.Sprintf("%v-%v", i.GetName(), "settings")
}
if len(s.ObjectMeta.Namespace) == 0 {
s.ObjectMeta.Namespace = i.GetNamespace()
}
}
func CreateAndInitSettings(i instance.Settings) *Settings {
return &Settings{
ObjectMeta: &meta.ObjectMeta{
Name: i.GetMeta().GetName(),
Namespace: i.GetMeta().GetNamespace(),
Labels: instance.InstanceLabels(i.GetMeta()),
},
Parameters: *i.GetParameters().Parameters,
}
}
*/
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