mirror of
https://github.com/jenkinsci/kubernetes-operator.git
synced 2026-10-05 23:51:12 +02:00
Initial version of user reconciliation loop and seed jobs
This commit is contained in:
@@ -93,7 +93,7 @@ func New(url, user, passwordOrToken string) (Jenkins, error) {
|
||||
return nil, err
|
||||
}
|
||||
if status != http.StatusOK {
|
||||
return nil, fmt.Errorf("Invalid status code returned: %d", status)
|
||||
return nil, fmt.Errorf("invalid status code returned: %d", status)
|
||||
}
|
||||
|
||||
return jenkinsClient, nil
|
||||
|
||||
@@ -45,59 +45,59 @@ func New(client client.Client, scheme *runtime.Scheme, logger logr.Logger,
|
||||
}
|
||||
|
||||
// Reconcile takes care of base configuration
|
||||
func (r *ReconcileJenkinsBaseConfiguration) Reconcile() (*reconcile.Result, error) {
|
||||
func (r *ReconcileJenkinsBaseConfiguration) Reconcile() (*reconcile.Result, jenkinsclient.Jenkins, error) {
|
||||
if !r.validate(r.jenkins) {
|
||||
r.logger.V(log.VWarn).Info("Please correct Jenkins CR")
|
||||
return &reconcile.Result{}, nil
|
||||
return &reconcile.Result{}, nil, nil
|
||||
}
|
||||
|
||||
metaObject := resources.NewResourceObjectMeta(r.jenkins)
|
||||
|
||||
if err := r.createOperatorCredentialsSecret(metaObject); err != nil {
|
||||
return &reconcile.Result{}, err
|
||||
return &reconcile.Result{}, nil, err
|
||||
}
|
||||
r.logger.V(log.VDebug).Info("Operator credentials secret is present")
|
||||
|
||||
if err := r.createScriptsConfigMap(metaObject); err != nil {
|
||||
return &reconcile.Result{}, err
|
||||
return &reconcile.Result{}, nil, err
|
||||
}
|
||||
r.logger.V(log.VDebug).Info("Scripts config map is present")
|
||||
|
||||
if err := r.createBaseConfigurationConfigMap(metaObject); err != nil {
|
||||
return &reconcile.Result{}, err
|
||||
return &reconcile.Result{}, nil, err
|
||||
}
|
||||
r.logger.V(log.VDebug).Info("Base configuration config map is present")
|
||||
|
||||
if err := r.createService(metaObject); err != nil {
|
||||
return &reconcile.Result{}, err
|
||||
return &reconcile.Result{}, nil, err
|
||||
}
|
||||
r.logger.V(log.VDebug).Info("Service is present")
|
||||
|
||||
result, err := r.createJenkinsMasterPod(metaObject)
|
||||
if err != nil {
|
||||
return &reconcile.Result{}, err
|
||||
return &reconcile.Result{}, nil, err
|
||||
}
|
||||
if result != nil {
|
||||
return result, nil
|
||||
return result, nil, nil
|
||||
}
|
||||
r.logger.V(log.VDebug).Info("Jenkins master pod is present")
|
||||
|
||||
result, err = r.waitForJenkins(metaObject)
|
||||
if err != nil {
|
||||
return &reconcile.Result{}, err
|
||||
return &reconcile.Result{}, nil, err
|
||||
}
|
||||
if result != nil {
|
||||
return result, nil
|
||||
return result, nil, nil
|
||||
}
|
||||
r.logger.V(log.VDebug).Info("Jenkins master pod is ready")
|
||||
|
||||
_, err = r.getJenkinsClient(metaObject)
|
||||
jenkinsClient, err := r.getJenkinsClient(metaObject)
|
||||
if err != nil {
|
||||
return &reconcile.Result{}, err
|
||||
return &reconcile.Result{}, nil, err
|
||||
}
|
||||
r.logger.V(log.VDebug).Info("Jenkins API client set")
|
||||
|
||||
return nil, nil
|
||||
return nil, jenkinsClient, nil
|
||||
}
|
||||
|
||||
func (r *ReconcileJenkinsBaseConfiguration) createOperatorCredentialsSecret(meta metav1.ObjectMeta) error {
|
||||
@@ -240,6 +240,7 @@ func (r *ReconcileJenkinsBaseConfiguration) waitForJenkins(meta metav1.ObjectMet
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// FIXME(bantoniak) move jenkins client out of base.reconcile because it's needed for user.reconcile as well
|
||||
func (r *ReconcileJenkinsBaseConfiguration) getJenkinsClient(meta metav1.ObjectMeta) (jenkinsclient.Jenkins, error) {
|
||||
jenkinsURL, err := jenkinsclient.BuildJenkinsAPIUrl(
|
||||
r.jenkins.ObjectMeta.Namespace, meta.Name, resources.HTTPPortInt, r.local, r.minikube)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"text/template"
|
||||
|
||||
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/render"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -40,7 +41,7 @@ func buildCreateJenkinsOperatorUserGroovyScript() (*string, error) {
|
||||
OperatorPasswordFile: OperatorCredentialsSecretPasswordKey,
|
||||
}
|
||||
|
||||
output, err := renderTemplate(createOperatorUserGroovyFmtTemplate, data)
|
||||
output, err := render.Render(createOperatorUserGroovyFmtTemplate, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/render"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
@@ -18,6 +19,19 @@ set -x
|
||||
mkdir -p {{ .JenkinsHomePath }}/init.groovy.d
|
||||
cp -n {{ .BaseConfigurationPath }}/*.groovy {{ .JenkinsHomePath }}/init.groovy.d
|
||||
|
||||
touch {{ .JenkinsHomePath }}/plugins.txt
|
||||
cat > {{ .JenkinsHomePath }}/plugins.txt <<EOL
|
||||
credentials:2.1.18
|
||||
ssh-credentials:1.14
|
||||
job-dsl:1.70
|
||||
git:3.9.1
|
||||
workflow-cps:2.61
|
||||
workflow-job:2.30
|
||||
workflow-aggregator:2.6
|
||||
EOL
|
||||
|
||||
/usr/local/bin/install-plugins.sh < {{ .JenkinsHomePath }}/plugins.txt
|
||||
|
||||
/sbin/tini -s -- /usr/local/bin/jenkins.sh
|
||||
`))
|
||||
|
||||
@@ -37,7 +51,7 @@ func buildInitBashScript() (*string, error) {
|
||||
BaseConfigurationPath: jenkinsBaseConfigurationVolumePath,
|
||||
}
|
||||
|
||||
output, err := renderTemplate(initBashTemplate, data)
|
||||
output, err := render.Render(initBashTemplate, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||
jenkins "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/client"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/user/seedjobs"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/log"
|
||||
"github.com/go-logr/logr"
|
||||
k8s "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
)
|
||||
|
||||
// ReconcileUserConfiguration defines values required for Jenkins user configuration
|
||||
type ReconcileUserConfiguration struct {
|
||||
k8sClient k8s.Client
|
||||
jenkinsClient jenkins.Jenkins
|
||||
logger logr.Logger
|
||||
jenkins *virtuslabv1alpha1.Jenkins
|
||||
}
|
||||
|
||||
// New create structure which takes care of user configuration
|
||||
func New(k8sClient k8s.Client, jenkinsClient jenkins.Jenkins, logger logr.Logger,
|
||||
jenkins *virtuslabv1alpha1.Jenkins) *ReconcileUserConfiguration {
|
||||
return &ReconcileUserConfiguration{
|
||||
k8sClient: k8sClient,
|
||||
jenkinsClient: jenkinsClient,
|
||||
logger: logger,
|
||||
jenkins: jenkins,
|
||||
}
|
||||
}
|
||||
|
||||
// Reconcile it's a main reconciliation loop for user supplied configuration
|
||||
func (r *ReconcileUserConfiguration) Reconcile() (*reconcile.Result, error) {
|
||||
if !r.validate(r.jenkins) {
|
||||
r.logger.V(log.VWarn).Info("Please correct Jenkins CR")
|
||||
return &reconcile.Result{}, nil
|
||||
}
|
||||
|
||||
err := seedjobs.ConfigureSeedJobs(r.jenkinsClient, r.k8sClient, r.jenkins)
|
||||
if err != nil {
|
||||
return &reconcile.Result{}, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
// Package seedjobs implements seed jobs configuration
|
||||
package seedjobs
|
||||
@@ -0,0 +1,221 @@
|
||||
package seedjobs
|
||||
|
||||
import (
|
||||
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||
jenkins "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/client"
|
||||
k8s "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"context"
|
||||
"fmt"
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// ConfigureSeedJobsName this is the job name
|
||||
ConfigureSeedJobsName = "Configure Seed Jobs"
|
||||
|
||||
deployKeyIDParameterName = "DEPLOY_KEY_ID"
|
||||
privateKeyParameterName = "PRIVATE_KEY"
|
||||
repositoryURLParameterName = "REPOSITORY_URL"
|
||||
repositoryBranchParameterName = "REPOSITORY_BRANCH"
|
||||
targetsParameterName = "TARGETS"
|
||||
displayNameParameterName = "SEED_JOB_DISPLAY_NAME"
|
||||
)
|
||||
|
||||
// ConfigureSeedJobs configures and triggers seed job pipeline for every Jenkins.Spec.SeedJobs entry
|
||||
func ConfigureSeedJobs(jenkinsClient jenkins.Jenkins, k8sClient k8s.Client, jenkins *virtuslabv1alpha1.Jenkins) error {
|
||||
err := configureSeedJobsPipeline(jenkinsClient)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
seedJobs := jenkins.Spec.SeedJobs
|
||||
for _, seedJob := range seedJobs {
|
||||
privateKey, err := extractPrivateKey(k8sClient, jenkins.Namespace, seedJob)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = triggerConfigureSeedJobsPipeline(
|
||||
jenkinsClient,
|
||||
seedJob.ID,
|
||||
privateKey,
|
||||
seedJob.RepositoryURL,
|
||||
seedJob.RepositoryBranch, seedJob.Targets, fmt.Sprintf("Seed Job from %s", seedJob.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// configureSeedJobsPipeline configures seed jobs and deploy keys
|
||||
func configureSeedJobsPipeline(jenkinsClient jenkins.Jenkins) error {
|
||||
// FIXME(bantoniak) implement CreateOrUpdateJob()
|
||||
_, err := jenkinsClient.CreateJob(seedJobConfigXML, ConfigureSeedJobsName)
|
||||
if err != nil && strings.Contains(err.Error(), "A job already exists") {
|
||||
// skip, job already exists
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// triggerConfigureSeedJobsPipeline triggers and configures seed job for specific GitHub repository
|
||||
func triggerConfigureSeedJobsPipeline(jenkinsClient jenkins.Jenkins, deployKeyID, privateKey, repositoryURL, repositoryBranch, targets, displayName string) error {
|
||||
options := map[string]string{
|
||||
deployKeyIDParameterName: deployKeyID,
|
||||
privateKeyParameterName: privateKey,
|
||||
repositoryURLParameterName: repositoryURL,
|
||||
repositoryBranchParameterName: repositoryBranch,
|
||||
targetsParameterName: targets,
|
||||
displayNameParameterName: displayName,
|
||||
}
|
||||
// FIXME(bantoniak) implement EnsureJob()
|
||||
_, err := jenkinsClient.BuildJob(ConfigureSeedJobsName, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractPrivateKey(k8sClient k8s.Client, namespace string, seedJob virtuslabv1alpha1.SeedJob) (string, error) {
|
||||
if seedJob.PrivateKey.SecretKeyRef != nil {
|
||||
deployKeySecret := &v1.Secret{}
|
||||
namespaceName := types.NamespacedName{Namespace: namespace, Name: seedJob.PrivateKey.SecretKeyRef.Name}
|
||||
err := k8sClient.Get(context.TODO(), namespaceName, deployKeySecret)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(deployKeySecret.Data[seedJob.PrivateKey.SecretKeyRef.Key]), nil
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// FIXME use mask-password plugin for params.PRIVATE_KEY
|
||||
var seedJobConfigXML = `
|
||||
<flow-definition plugin="workflow-job@2.30">
|
||||
<actions/>
|
||||
<description></description>
|
||||
<keepDependencies>false</keepDependencies>
|
||||
<properties>
|
||||
<hudson.model.ParametersDefinitionProperty>
|
||||
<parameterDefinitions>
|
||||
<hudson.model.StringParameterDefinition>
|
||||
<name>DEPLOY_KEY_ID</name>
|
||||
<description></description>
|
||||
<defaultValue></defaultValue>
|
||||
<trim>false</trim>
|
||||
</hudson.model.StringParameterDefinition>
|
||||
<hudson.model.StringParameterDefinition>
|
||||
<name>PRIVATE_KEY</name>
|
||||
<description></description>
|
||||
<defaultValue></defaultValue>
|
||||
</hudson.model.StringParameterDefinition>
|
||||
<hudson.model.StringParameterDefinition>
|
||||
<name>REPOSITORY_URL</name>
|
||||
<description></description>
|
||||
<defaultValue></defaultValue>
|
||||
<trim>false</trim>
|
||||
</hudson.model.StringParameterDefinition>
|
||||
<hudson.model.StringParameterDefinition>
|
||||
<name>REPOSITORY_BRANCH</name>
|
||||
<description></description>
|
||||
<defaultValue>master</defaultValue>
|
||||
<trim>false</trim>
|
||||
</hudson.model.StringParameterDefinition>
|
||||
<hudson.model.StringParameterDefinition>
|
||||
<name>SEED_JOB_DISPLAY_NAME</name>
|
||||
<description></description>
|
||||
<defaultValue></defaultValue>
|
||||
<trim>false</trim>
|
||||
</hudson.model.StringParameterDefinition>
|
||||
<hudson.model.StringParameterDefinition>
|
||||
<name>TARGETS</name>
|
||||
<description></description>
|
||||
<defaultValue>cicd/jobs/*.jenkins</defaultValue>
|
||||
<trim>false</trim>
|
||||
</hudson.model.StringParameterDefinition>
|
||||
</parameterDefinitions>
|
||||
</hudson.model.ParametersDefinitionProperty>
|
||||
</properties>
|
||||
<definition class="org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition" plugin="workflow-cps@2.61">
|
||||
<script>import com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey
|
||||
import com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey.DirectEntryPrivateKeySource
|
||||
import com.cloudbees.plugins.credentials.CredentialsScope
|
||||
import com.cloudbees.plugins.credentials.SystemCredentialsProvider
|
||||
import com.cloudbees.plugins.credentials.domains.Domain
|
||||
import hudson.model.FreeStyleProject
|
||||
import hudson.model.labels.LabelAtom
|
||||
import hudson.plugins.git.BranchSpec
|
||||
import hudson.plugins.git.GitSCM
|
||||
import hudson.plugins.git.SubmoduleConfig
|
||||
import hudson.plugins.git.extensions.impl.CloneOption
|
||||
import javaposse.jobdsl.plugin.ExecuteDslScripts
|
||||
import javaposse.jobdsl.plugin.LookupStrategy
|
||||
import javaposse.jobdsl.plugin.RemovedJobAction
|
||||
import javaposse.jobdsl.plugin.RemovedViewAction
|
||||
import jenkins.model.Jenkins
|
||||
import javaposse.jobdsl.plugin.GlobalJobDslSecurityConfiguration
|
||||
import jenkins.model.GlobalConfiguration
|
||||
|
||||
import static com.google.common.collect.Lists.newArrayList
|
||||
|
||||
// https://javadoc.jenkins.io/plugin/ssh-credentials/com/cloudbees/jenkins/plugins/sshcredentials/impl/BasicSSHUserPrivateKey.html
|
||||
BasicSSHUserPrivateKey deployKeyPrivate = new BasicSSHUserPrivateKey(
|
||||
CredentialsScope.GLOBAL,
|
||||
"${params.DEPLOY_KEY_ID}",
|
||||
"git",
|
||||
new DirectEntryPrivateKeySource("${params.PRIVATE_KEY}"),
|
||||
"",
|
||||
"${params.DEPLOY_KEY_ID}"
|
||||
)
|
||||
|
||||
// https://javadoc.jenkins.io/plugin/credentials/index.html?com/cloudbees/plugins/credentials/SystemCredentialsProvider.html
|
||||
SystemCredentialsProvider.getInstance().getStore().addCredentials(Domain.global(), deployKeyPrivate)
|
||||
|
||||
Jenkins jenkins = Jenkins.instance
|
||||
|
||||
|
||||
def jobDslSeedName = "${params.DEPLOY_KEY_ID}-job-dsl-seed"
|
||||
def jobDslDeployKeyName = "${params.DEPLOY_KEY_ID}"
|
||||
def jobRef = jenkins.getItem(jobDslSeedName)
|
||||
|
||||
def repoList = GitSCM.createRepoList("${params.REPOSITORY_URL}", jobDslDeployKeyName)
|
||||
def gitExtensions = [new CloneOption(true, true, "", 10)]
|
||||
def scm = new GitSCM(
|
||||
repoList,
|
||||
newArrayList(new BranchSpec("${params.REPOSITORY_BRANCH}")),
|
||||
false,
|
||||
Collections.<SubmoduleConfig> emptyList(),
|
||||
null,
|
||||
null,
|
||||
gitExtensions
|
||||
)
|
||||
|
||||
def executeDslScripts = new ExecuteDslScripts()
|
||||
executeDslScripts.setTargets("${params.TARGETS}")
|
||||
executeDslScripts.setSandbox(false)
|
||||
executeDslScripts.setRemovedJobAction(RemovedJobAction.DELETE)
|
||||
executeDslScripts.setRemovedViewAction(RemovedViewAction.DELETE)
|
||||
executeDslScripts.setLookupStrategy(LookupStrategy.SEED_JOB)
|
||||
executeDslScripts.setAdditionalClasspath("src")
|
||||
|
||||
if (jobRef == null) {
|
||||
jobRef = jenkins.createProject(FreeStyleProject, jobDslSeedName)
|
||||
}
|
||||
jobRef.getBuildersList().clear()
|
||||
jobRef.getBuildersList().add(executeDslScripts)
|
||||
jobRef.setDisplayName("${params.SEED_JOB_DISPLAY_NAME}")
|
||||
jobRef.setScm(scm)
|
||||
jobRef.setAssignedLabel(new LabelAtom("master"))
|
||||
|
||||
// disable Job DSL script approval
|
||||
GlobalConfiguration.all().get(GlobalJobDslSecurityConfiguration.class).useScriptSecurity=false
|
||||
GlobalConfiguration.all().get(GlobalJobDslSecurityConfiguration.class).save()</script>
|
||||
<sandbox>false</sandbox>
|
||||
</definition>
|
||||
<triggers/>
|
||||
<disabled>false</disabled>
|
||||
</flow-definition>
|
||||
`
|
||||
@@ -0,0 +1,26 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (r *ReconcileUserConfiguration) validate(jenkins *virtuslabv1alpha1.Jenkins) bool {
|
||||
// validate jenkins.Spec.SeedJobs
|
||||
if jenkins.Spec.SeedJobs != nil {
|
||||
for _, seedJob := range jenkins.Spec.SeedJobs {
|
||||
if len(seedJob.ID) == 0 {
|
||||
r.logger.V(0).Info("seed job id can't be empty")
|
||||
return false
|
||||
}
|
||||
|
||||
if strings.Contains(seedJob.RepositoryURL, "git@") {
|
||||
if seedJob.PrivateKey.SecretKeyRef == nil {
|
||||
r.logger.V(0).Info("private key can't be empty while using ssh repository url")
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/base"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/user"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/log"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
@@ -74,8 +75,8 @@ type ReconcileJenkins struct {
|
||||
local, minikube bool
|
||||
}
|
||||
|
||||
// Reconcile reads that state of the cluster for a Jenkins object and makes changes based on the state read
|
||||
// and what is in the Jenkins.Spec
|
||||
// Reconcile it's a main reconciliation loop which maintain desired state for on Jenkins.Spec
|
||||
// including base and user supplied configuration
|
||||
func (r *ReconcileJenkins) Reconcile(request reconcile.Request) (reconcile.Result, error) {
|
||||
logger := r.buildLogger(request.Name)
|
||||
logger.Info("Reconciling Jenkins")
|
||||
@@ -94,8 +95,9 @@ func (r *ReconcileJenkins) Reconcile(request reconcile.Request) (reconcile.Resul
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
// Reconcile base configuration
|
||||
baseConfiguration := base.New(r.client, r.scheme, logger, jenkins, r.local, r.minikube)
|
||||
result, err := baseConfiguration.Reconcile()
|
||||
result, jenkinsClient, err := baseConfiguration.Reconcile()
|
||||
if err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
@@ -111,6 +113,24 @@ func (r *ReconcileJenkins) Reconcile(request reconcile.Request) (reconcile.Resul
|
||||
}
|
||||
}
|
||||
|
||||
// Reconcile user configuration
|
||||
userConfiguration := user.New(r.client, jenkinsClient, logger, jenkins)
|
||||
result, err = userConfiguration.Reconcile()
|
||||
if err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
if result != nil {
|
||||
return *result, nil
|
||||
}
|
||||
if err == nil && result == nil && jenkins.Status.UserConfigurationCompletedTime == nil {
|
||||
now := metav1.Now()
|
||||
jenkins.Status.UserConfigurationCompletedTime = &now
|
||||
err = r.client.Update(context.TODO(), jenkins)
|
||||
if err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
}
|
||||
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -1,11 +1,12 @@
|
||||
package resources
|
||||
package render
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
func renderTemplate(template *template.Template, data interface{}) (string, error) {
|
||||
// Render executes a parsed template (go-template) with configuration from data
|
||||
func Render(template *template.Template, data interface{}) (string, error) {
|
||||
var buffer bytes.Buffer
|
||||
if err := template.Execute(&buffer, data); err != nil {
|
||||
return "", err
|
||||
Reference in New Issue
Block a user