package casc import ( "crypto/sha256" "encoding/base64" "fmt" "sort" "strings" "github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkinsio/v1alpha1" jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/client" "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/jobs" "github.com/go-logr/logr" k8s "sigs.k8s.io/controller-runtime/pkg/client" ) const ( jobHashParameterName = "hash" ) // ConfigurationAsCode defines API which configures Jenkins with help Configuration as a code plugin type ConfigurationAsCode struct { jenkinsClient jenkinsclient.Jenkins k8sClient k8s.Client logger logr.Logger jobName string configsPath string } // New creates new instance of ConfigurationAsCode func New(jenkinsClient jenkinsclient.Jenkins, k8sClient k8s.Client, logger logr.Logger, jobName, configsPath string) *ConfigurationAsCode { return &ConfigurationAsCode{ jenkinsClient: jenkinsClient, k8sClient: k8sClient, logger: logger, jobName: jobName, configsPath: configsPath, } } // ConfigureJob configures jenkins job which configures Jenkins with help Configuration as a code plugin func (g *ConfigurationAsCode) ConfigureJob() error { _, created, err := g.jenkinsClient.CreateOrUpdateJob(fmt.Sprintf(configurationJobXMLFmt, g.configsPath), g.jobName) if err != nil { return err } if created { g.logger.Info(fmt.Sprintf("'%s' job has been created", g.jobName)) } return nil } // Ensure configures Jenkins with help Configuration as a code plugin func (g *ConfigurationAsCode) Ensure(secretOrConfigMapData map[string]string, jenkins *v1alpha1.Jenkins) (bool, error) { jobsClient := jobs.New(g.jenkinsClient, g.k8sClient, g.logger) hash := g.calculateHash(secretOrConfigMapData) done, err := jobsClient.EnsureBuildJob(g.jobName, hash, map[string]string{jobHashParameterName: hash}, jenkins, true) if err != nil { return false, err } return done, nil } func (g *ConfigurationAsCode) calculateHash(secretOrConfigMapData map[string]string) string { hash := sha256.New() var keys []string for key := range secretOrConfigMapData { keys = append(keys, key) } sort.Strings(keys) for _, key := range keys { if strings.HasSuffix(key, ".yaml") { hash.Write([]byte(key)) hash.Write([]byte(secretOrConfigMapData[key])) } } return base64.StdEncoding.EncodeToString(hash.Sum(nil)) } const configurationJobXMLFmt = ` false ` + jobHashParameterName + ` false false false `