#199 Generalize Jenkins container command validation
This commit is contained in:
parent
bf3a4bc02f
commit
bf07fa59ef
|
|
@ -237,6 +237,22 @@ func (in *Jenkins) DeepCopyObject() runtime.Object {
|
|||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JenkinsAPISettings) DeepCopyInto(out *JenkinsAPISettings) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsAPISettings.
|
||||
func (in *JenkinsAPISettings) DeepCopy() *JenkinsAPISettings {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JenkinsAPISettings)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JenkinsList) DeepCopyInto(out *JenkinsList) {
|
||||
*out = *in
|
||||
|
|
@ -376,6 +392,7 @@ func (in *JenkinsSpec) DeepCopyInto(out *JenkinsSpec) {
|
|||
copy(*out, *in)
|
||||
}
|
||||
in.ServiceAccount.DeepCopyInto(&out.ServiceAccount)
|
||||
out.JenkinsAPISettings = in.JenkinsAPISettings
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -484,11 +484,6 @@ func (r *ReconcileJenkinsBaseConfiguration) ensureJenkinsMasterPod(meta metav1.O
|
|||
currentJenkinsMasterPod, err := r.getJenkinsMasterPod()
|
||||
if err != nil && apierrors.IsNotFound(err) {
|
||||
jenkinsMasterPod := resources.NewJenkinsMasterPod(meta, r.Configuration.Jenkins)
|
||||
if !reflect.DeepEqual(jenkinsMasterPod.Spec.Containers[0].Command, resources.GetJenkinsMasterContainerBaseCommand()) {
|
||||
r.logger.Info(fmt.Sprintf("spec.master.containers[%s].command has been overridden make sure the command looks like: '%v', otherwise the operator won't configure default user and install plugins",
|
||||
resources.JenkinsMasterContainerName, []string{"bash", "-c", fmt.Sprintf("%s/%s && <custom-command-here> && /sbin/tini -s -- /usr/local/bin/jenkins.sh",
|
||||
resources.JenkinsScriptsVolumePath, resources.InitScriptName)}))
|
||||
}
|
||||
*r.Notifications <- event.Event{
|
||||
Jenkins: *r.Configuration.Jenkins,
|
||||
Phase: event.PhaseBase,
|
||||
|
|
|
|||
|
|
@ -69,6 +69,38 @@ func (r *ReconcileJenkinsBaseConfiguration) Validate(jenkins *v1alpha2.Jenkins)
|
|||
return messages, nil
|
||||
}
|
||||
|
||||
func (r *ReconcileJenkinsBaseConfiguration) validateJenkinsMasterContainerCommand() []string {
|
||||
masterContainer := r.Configuration.GetJenkinsMasterContainer()
|
||||
if masterContainer == nil {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
jenkinsOperatorInitScript := fmt.Sprintf("%s/%s && ", resources.JenkinsScriptsVolumePath, resources.InitScriptName)
|
||||
correctCommand := []string{
|
||||
"bash",
|
||||
"-c",
|
||||
fmt.Sprintf("%s<optional-custom-command> && exec <command-which-start-jenkins>", jenkinsOperatorInitScript),
|
||||
}
|
||||
invalidCommandMessage := []string{fmt.Sprintf("spec.master.containers[%s].command is invalid, make sure it looks like '%v', otherwise the operator won't configure default user and install plugins. 'exec' is required to propagate signals to the Jenkins.", masterContainer.Name, correctCommand)}
|
||||
if len(masterContainer.Command) != 3 {
|
||||
return invalidCommandMessage
|
||||
}
|
||||
if masterContainer.Command[0] != correctCommand[0] {
|
||||
return invalidCommandMessage
|
||||
}
|
||||
if masterContainer.Command[1] != correctCommand[1] {
|
||||
return invalidCommandMessage
|
||||
}
|
||||
if !strings.HasPrefix(masterContainer.Command[2], jenkinsOperatorInitScript) {
|
||||
return invalidCommandMessage
|
||||
}
|
||||
if !strings.Contains(masterContainer.Command[2], "exec") {
|
||||
return invalidCommandMessage
|
||||
}
|
||||
|
||||
return []string{}
|
||||
}
|
||||
|
||||
func (r *ReconcileJenkinsBaseConfiguration) validateImagePullSecrets() ([]string, error) {
|
||||
var messages []string
|
||||
for _, sr := range r.Configuration.Jenkins.Spec.Master.ImagePullSecrets {
|
||||
|
|
|
|||
|
|
@ -840,3 +840,123 @@ func TestValidateCustomization(t *testing.T) {
|
|||
assert.Equal(t, got, []string{"ConfigMap 'configmap-name' configured in spec.groovyScripts.configurations[0] not found"})
|
||||
})
|
||||
}
|
||||
|
||||
func TestValidateJenkinsMasterContainerCommand(t *testing.T) {
|
||||
log.SetupLogger(true)
|
||||
t.Run("no Jenkins master container", func(t *testing.T) {
|
||||
jenkins := &v1alpha2.Jenkins{}
|
||||
baseReconcileLoop := New(configuration.Configuration{Jenkins: jenkins}, log.Log, client.JenkinsAPIConnectionSettings{})
|
||||
|
||||
got := baseReconcileLoop.validateJenkinsMasterContainerCommand()
|
||||
|
||||
assert.Empty(t, got)
|
||||
})
|
||||
t.Run("empty command", func(t *testing.T) {
|
||||
jenkins := &v1alpha2.Jenkins{
|
||||
Spec: v1alpha2.JenkinsSpec{
|
||||
Master: v1alpha2.JenkinsMaster{
|
||||
Containers: []v1alpha2.Container{
|
||||
{
|
||||
Name: resources.JenkinsMasterContainerName,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
baseReconcileLoop := New(configuration.Configuration{Jenkins: jenkins}, log.Log, client.JenkinsAPIConnectionSettings{})
|
||||
|
||||
got := baseReconcileLoop.validateJenkinsMasterContainerCommand()
|
||||
|
||||
assert.Len(t, got, 1)
|
||||
})
|
||||
t.Run("command has 3 lines but it's values are invalid", func(t *testing.T) {
|
||||
jenkins := &v1alpha2.Jenkins{
|
||||
Spec: v1alpha2.JenkinsSpec{
|
||||
Master: v1alpha2.JenkinsMaster{
|
||||
Containers: []v1alpha2.Container{
|
||||
{
|
||||
Name: resources.JenkinsMasterContainerName,
|
||||
Command: []string{
|
||||
"invalid",
|
||||
"invalid",
|
||||
"invalid",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
baseReconcileLoop := New(configuration.Configuration{Jenkins: jenkins}, log.Log, client.JenkinsAPIConnectionSettings{})
|
||||
|
||||
got := baseReconcileLoop.validateJenkinsMasterContainerCommand()
|
||||
|
||||
assert.Len(t, got, 1)
|
||||
})
|
||||
t.Run("valid command", func(t *testing.T) {
|
||||
jenkins := &v1alpha2.Jenkins{
|
||||
Spec: v1alpha2.JenkinsSpec{
|
||||
Master: v1alpha2.JenkinsMaster{
|
||||
Containers: []v1alpha2.Container{
|
||||
{
|
||||
Name: resources.JenkinsMasterContainerName,
|
||||
Command: resources.GetJenkinsMasterContainerBaseCommand(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
baseReconcileLoop := New(configuration.Configuration{Jenkins: jenkins}, log.Log, client.JenkinsAPIConnectionSettings{})
|
||||
|
||||
got := baseReconcileLoop.validateJenkinsMasterContainerCommand()
|
||||
|
||||
assert.Len(t, got, 0)
|
||||
})
|
||||
t.Run("custom valid command", func(t *testing.T) {
|
||||
jenkins := &v1alpha2.Jenkins{
|
||||
Spec: v1alpha2.JenkinsSpec{
|
||||
Master: v1alpha2.JenkinsMaster{
|
||||
Containers: []v1alpha2.Container{
|
||||
{
|
||||
Name: resources.JenkinsMasterContainerName,
|
||||
Command: []string{
|
||||
"bash",
|
||||
"-c",
|
||||
fmt.Sprintf("%s/%s && my-extra-command.sh && exec /sbin/tini -s -- /usr/local/bin/jenkins.sh",
|
||||
resources.JenkinsScriptsVolumePath, resources.InitScriptName),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
baseReconcileLoop := New(configuration.Configuration{Jenkins: jenkins}, log.Log, client.JenkinsAPIConnectionSettings{})
|
||||
|
||||
got := baseReconcileLoop.validateJenkinsMasterContainerCommand()
|
||||
|
||||
assert.Len(t, got, 0)
|
||||
})
|
||||
t.Run("no exec command for the Jenkins", func(t *testing.T) {
|
||||
jenkins := &v1alpha2.Jenkins{
|
||||
Spec: v1alpha2.JenkinsSpec{
|
||||
Master: v1alpha2.JenkinsMaster{
|
||||
Containers: []v1alpha2.Container{
|
||||
{
|
||||
Name: resources.JenkinsMasterContainerName,
|
||||
Command: []string{
|
||||
"bash",
|
||||
"-c",
|
||||
fmt.Sprintf("%s/%s && my-extra-command.sh && /sbin/tini -s -- /usr/local/bin/jenkins.sh",
|
||||
resources.JenkinsScriptsVolumePath, resources.InitScriptName),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
baseReconcileLoop := New(configuration.Configuration{Jenkins: jenkins}, log.Log, client.JenkinsAPIConnectionSettings{})
|
||||
|
||||
got := baseReconcileLoop.validateJenkinsMasterContainerCommand()
|
||||
|
||||
assert.Len(t, got, 1)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,3 +150,12 @@ func (c *Configuration) Exec(podName, containerName string, command []string) (s
|
|||
|
||||
return
|
||||
}
|
||||
|
||||
// GetJenkinsMasterContainer returns the Jenkins master container from the CR
|
||||
func (c *Configuration) GetJenkinsMasterContainer() *v1alpha2.Container {
|
||||
if len(c.Jenkins.Spec.Master.Containers) > 0 {
|
||||
// the first container is the Jenkins master, it is forced jenkins_controller.go
|
||||
return &c.Jenkins.Spec.Master.Containers[0]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue