Skip to content
settings.go 5.96 KiB
Newer Older
Timothee Gosselin's avatar
Timothee Gosselin committed
/*

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 (
Timothee Gosselin's avatar
Timothee Gosselin committed
	"crypto/sha1"
	"fmt"
	"io"
	"sort"
	"strings"
Timothee Gosselin's avatar
Timothee Gosselin committed
	"k8s.libre.sh/controller-utils/application/settings/parameters"
	"k8s.libre.sh/controller-utils/meta"
	"k8s.libre.sh/controller-utils/objects"
Timothee Gosselin's avatar
Timothee Gosselin committed
)

Timothee Gosselin's avatar
Timothee Gosselin committed
const (
	// Generate settings as env variables in a configMap or Secret
	GenEnvFile SettingsGenerate = "envFile"
)
Timothee Gosselin's avatar
Timothee Gosselin committed
const (
	// Generate settings as env variables in a configMap or Secret
	SecretSettings SettingsType = "secret"
)
Timothee Gosselin's avatar
Timothee Gosselin committed
type SettingsGenerate string
type SettingsType string
Timothee Gosselin's avatar
Timothee Gosselin committed
// +kubebuilder:object:generate=true
type Settings struct {
	CreateOptions *CreateOptions `json:"createOptions,omitempty"`
	*SettingsSpec `json:",inline"`
Timothee Gosselin's avatar
Timothee Gosselin committed
// +kubebuilder:object:generate=true
type CreateOptions struct {
	CommonMeta   *meta.ObjectMeta `json:"commonMeta,omitempty"`
	SecretMeta   *meta.ObjectMeta `json:"secretMeta,omitempty"`
	ConfigMeta   *meta.ObjectMeta `json:"configMeta,omitempty"`
	Generate     SettingsGenerate `json:"generate,omitempty"`
	SettingsType SettingsType     `json:"type,omitempty"`
}
Timothee Gosselin's avatar
Timothee Gosselin committed
// NewSettings returns a Settings struct
func NewSettings(co *CreateOptions, srcs *Sources, ps *parameters.Parameters) *Settings {
Timothee Gosselin's avatar
Timothee Gosselin committed
	return &Settings{
		CreateOptions: co,
Timothee Gosselin's avatar
Timothee Gosselin committed
		SettingsSpec: &SettingsSpec{
			Sources:    srcs,
			Parameters: ps,
Timothee Gosselin's avatar
Timothee Gosselin committed
		},
Timothee Gosselin's avatar
Timothee Gosselin committed
	}
Timothee Gosselin's avatar
Timothee Gosselin committed
func (opts *CreateOptions) Init() {
	if opts.CommonMeta == nil {
		opts.CommonMeta = &meta.ObjectMeta{}
Timothee Gosselin's avatar
Timothee Gosselin committed
	}
Timothee Gosselin's avatar
Timothee Gosselin committed
	if opts.CommonMeta.Labels == nil {
		opts.CommonMeta.Labels = make(map[string]string)
Timothee Gosselin's avatar
Timothee Gosselin committed
	}
Timothee Gosselin's avatar
Timothee Gosselin committed
	if opts.SecretMeta == nil {
		opts.SecretMeta = &meta.ObjectMeta{}
Timothee Gosselin's avatar
Timothee Gosselin committed
	}
Timothee Gosselin's avatar
Timothee Gosselin committed

Timothee Gosselin's avatar
Timothee Gosselin committed
	if opts.SecretMeta.Labels == nil {
		opts.SecretMeta.Labels = make(map[string]string)
Timothee Gosselin's avatar
Timothee Gosselin committed
	if opts.ConfigMeta == nil {
		opts.ConfigMeta = &meta.ObjectMeta{}
Timothee Gosselin's avatar
Timothee Gosselin committed
	if opts.ConfigMeta.Labels == nil {
		opts.SecretMeta.Labels = make(map[string]string)
Timothee Gosselin's avatar
Timothee Gosselin committed
// GetCreateOptions return the CreateOptions
Timothee Gosselin's avatar
Timothee Gosselin committed
func (s *Settings) GetCreateOptions() *CreateOptions { return s.CreateOptions }
Timothee Gosselin's avatar
Timothee Gosselin committed
// GetConfig return the SettingsSpec
Timothee Gosselin's avatar
Timothee Gosselin committed
func (s *Settings) GetConfig() Config { return s.SettingsSpec }
Timothee Gosselin's avatar
Timothee Gosselin committed
// GetMeta return the  meta.Instance interface
Timothee Gosselin's avatar
Timothee Gosselin committed
func (s *Settings) GetMeta() meta.Instance { return s.CreateOptions.CommonMeta }
Timothee Gosselin's avatar
Timothee Gosselin committed
// GetCreateOptions return the CreateOptions
Timothee Gosselin's avatar
Timothee Gosselin committed
func (s *Settings) GetObjects() map[int]objects.Object { return GetObjects(s) }
Timothee Gosselin's avatar
Timothee Gosselin committed
// SetDefaults sets the defaults from the create options
Timothee Gosselin's avatar
Timothee Gosselin committed
func (s *Settings) SetDefaults() {
Timothee Gosselin's avatar
Timothee Gosselin committed

	srcs := &Sources{}

	secretSrc := Source{
		Ref:  s.GetCreateOptions().SecretMeta.GetName(),
		Type: "secret",
	}
	configSrc := Source{
		Ref:  s.GetCreateOptions().ConfigMeta.GetName(),
		Type: "configmap",
	}

	// Reset sources, we do not want to mount orginal resources
	if s.GetCreateOptions().Generate == GenEnvFile {
		srcs = &Sources{}
	}

Timothee Gosselin's avatar
Timothee Gosselin committed
	for _, p := range *s.GetParameters() {

		// TODO IMPROVE

		if p.MountType == parameters.MountEnvFile || (p.MountType != parameters.MountFile && s.GetCreateOptions().Generate == GenEnvFile) {
			if p.Type != parameters.ObjectFieldParameter || p.RefType != parameters.ObjectFieldParameter {
				p.MountType = parameters.MountEnvFile
				// add newly created resource ref to sources
				if p.Type == parameters.ConfigParameter {
					srcs = AppendSourceIfUnique(srcs, configSrc)
				} else if p.Type == parameters.SecretParameter || p.Type == "" {
					srcs = AppendSourceIfUnique(srcs, secretSrc)
				}
		if p.Type != parameters.ObjectFieldParameter || p.RefType != parameters.ObjectFieldParameter {
			if s.GetCreateOptions().SettingsType == "configmap" {
				p.Type = parameters.ConfigParameter
			} else if s.GetCreateOptions().SettingsType == "secret" {
				p.Type = parameters.SecretParameter
			}
Timothee Gosselin's avatar
Timothee Gosselin committed
		if p.MountType == parameters.MountFile && len(p.Ref) == 0 {
			if p.Type == parameters.ConfigParameter {
				p.Ref = s.GetCreateOptions().ConfigMeta.GetName()
Timothee Gosselin's avatar
Timothee Gosselin committed
			if p.Type == parameters.SecretParameter {
				p.Ref = s.GetCreateOptions().SecretMeta.GetName()
	}

	srcs.DeepCopyInto(s.GetSources())

Timothee Gosselin's avatar
Timothee Gosselin committed
	shaParam := &parameters.Parameter{
		Key:       s.GetMeta().GetComponent(),
		Value:     GetSHAfromParameters(s.GetParameters()),
		MountType: parameters.MountLiteral,
	}

	for _, p := range *s.GetParameters() {
		if p.Key == s.GetMeta().GetComponent() {
			p = shaParam
			return
		}
	}

	*s.GetParameters() = append(*s.GetParameters(), shaParam)

Timothee Gosselin's avatar
Timothee Gosselin committed
// Init initialise the settings.
// ObjectMeta are set from commons meta.
// Parameters are initialised from external resources set in ValueFrom and random values are generated.
Timothee Gosselin's avatar
Timothee Gosselin committed
/* func (s *Settings) Init(c client.Client, owner interfaces.Object, scheme *runtime.Scheme) error {
Timothee Gosselin's avatar
Timothee Gosselin committed
	if s.CreateOptions == nil {
		s.CreateOptions = &CreateOptions{}
Timothee Gosselin's avatar
Timothee Gosselin committed
	s.CreateOptions.Init()
Timothee Gosselin's avatar
Timothee Gosselin committed
	meta.SetObjectMeta(s.CreateOptions.CommonMeta, s.CreateOptions.ConfigMeta)
	meta.SetObjectMeta(s.CreateOptions.CommonMeta, s.CreateOptions.SecretMeta)
Timothee Gosselin's avatar
Timothee Gosselin committed
	err := InitParametersValueFrom(s, c, owner, scheme)
Timothee Gosselin's avatar
Timothee Gosselin committed
	if err != nil {
		return err
Timothee Gosselin's avatar
Timothee Gosselin committed
	s.InitRandValues()
Timothee Gosselin's avatar
Timothee Gosselin committed
	return nil
}
*/

func GetSHAfromParameters(params *parameters.Parameters) string {
	values := []string{}
	for _, p := range *params {
		if len(p.Key) > 0 && len(p.Value) > 0 {
			values = append(values, p.Key+"="+p.Value)
		}
Timothee Gosselin's avatar
Timothee Gosselin committed
	sort.Strings(values)

	return GenerateSHA(strings.Join(values, ";"))
}

// GenerateSHA generates SHA from string
func GenerateSHA(data string) string {
	hasher := sha1.New()
	_, err := io.WriteString(hasher, data)
	if err != nil {
		//	logrus.Errorf("Unable to write data in hash writer %v", err)
	}
	sha := hasher.Sum(nil)
	return fmt.Sprintf("%x", sha)