mirror of
https://github.com/jenkinsci/kubernetes-operator.git
synced 2026-10-08 09:01:15 +02:00
Prepare for Security Validator release (#680)
* Tidy up k8s events logging * Increase memory and decrease CPU in resources * Standarize API fields * Refactor tests * Change image and resources for e2e tests * Increase readability
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
// +kubebuilder:scaffold:imports
|
||||
)
|
||||
@@ -74,10 +76,10 @@ var _ = Describe("Jenkins controller configuration", func() {
|
||||
|
||||
BeforeEach(func() {
|
||||
namespace = CreateNamespace()
|
||||
|
||||
createUserConfigurationSecret(namespace.Name, userConfigurationSecretData)
|
||||
createUserConfigurationConfigMap(namespace.Name, numberOfExecutorsEnvName, fmt.Sprintf("${%s}", systemMessageEnvName))
|
||||
jenkins = createJenkinsCR(jenkinsCRName, namespace.Name, &[]v1alpha2.SeedJob{mySeedJob.SeedJob}, groovyScripts, casc, priorityClassName)
|
||||
jenkins = RenderJenkinsCR(jenkinsCRName, namespace.Name, &[]v1alpha2.SeedJob{mySeedJob.SeedJob}, groovyScripts, casc, priorityClassName)
|
||||
Expect(K8sClient.Create(context.TODO(), jenkins)).Should(Succeed())
|
||||
createDefaultLimitsForContainersInNamespace(namespace.Name)
|
||||
createKubernetesCredentialsProviderSecret(namespace.Name, mySeedJob)
|
||||
})
|
||||
@@ -125,7 +127,8 @@ var _ = Describe("Jenkins controller priority class", func() {
|
||||
|
||||
BeforeEach(func() {
|
||||
namespace = CreateNamespace()
|
||||
jenkins = createJenkinsCR(jenkinsCRName, namespace.Name, nil, groovyScripts, casc, priorityClassName)
|
||||
jenkins = RenderJenkinsCR(jenkinsCRName, namespace.Name, nil, groovyScripts, casc, priorityClassName)
|
||||
Expect(K8sClient.Create(context.TODO(), jenkins)).Should(Succeed())
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
@@ -177,7 +180,8 @@ var _ = Describe("Jenkins controller plugins test", func() {
|
||||
|
||||
BeforeEach(func() {
|
||||
namespace = CreateNamespace()
|
||||
jenkins = createJenkinsCR(jenkinsCRName, namespace.Name, &[]v1alpha2.SeedJob{mySeedJob.SeedJob}, groovyScripts, casc, priorityClassName)
|
||||
jenkins = RenderJenkinsCR(jenkinsCRName, namespace.Name, &[]v1alpha2.SeedJob{mySeedJob.SeedJob}, groovyScripts, casc, priorityClassName)
|
||||
Expect(K8sClient.Create(context.TODO(), jenkins)).Should(Succeed())
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
@@ -35,7 +37,8 @@ var _ = Describe("Jenkins controller", func() {
|
||||
namespace = CreateNamespace()
|
||||
|
||||
configureAuthorizationToUnSecure(namespace.Name, userConfigurationConfigMapName)
|
||||
jenkins = createJenkinsCR(jenkinsCRName, namespace.Name, nil, groovyScripts, casc, priorityClassName)
|
||||
jenkins = RenderJenkinsCR(jenkinsCRName, namespace.Name, nil, groovyScripts, casc, priorityClassName)
|
||||
Expect(K8sClient.Create(context.TODO(), jenkins)).Should(Succeed())
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
|
||||
+13
-107
@@ -15,6 +15,7 @@ import (
|
||||
. "github.com/onsi/gomega"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
@@ -46,112 +47,6 @@ func getJenkinsMasterPod(jenkins *v1alpha2.Jenkins) *corev1.Pod {
|
||||
return &pods.Items[0]
|
||||
}
|
||||
|
||||
func createJenkinsCR(name, namespace string, seedJob *[]v1alpha2.SeedJob, groovyScripts v1alpha2.GroovyScripts, casc v1alpha2.ConfigurationAsCode, priorityClassName string) *v1alpha2.Jenkins {
|
||||
var seedJobs []v1alpha2.SeedJob
|
||||
if seedJob != nil {
|
||||
seedJobs = append(seedJobs, *seedJob...)
|
||||
}
|
||||
|
||||
jenkins := &v1alpha2.Jenkins{
|
||||
TypeMeta: v1alpha2.JenkinsTypeMeta(),
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: v1alpha2.JenkinsSpec{
|
||||
GroovyScripts: groovyScripts,
|
||||
ConfigurationAsCode: casc,
|
||||
Master: v1alpha2.JenkinsMaster{
|
||||
Annotations: map[string]string{"test": "label"},
|
||||
Containers: []v1alpha2.Container{
|
||||
{
|
||||
Name: resources.JenkinsMasterContainerName,
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
Name: "TEST_ENV",
|
||||
Value: "test_env_value",
|
||||
},
|
||||
},
|
||||
ReadinessProbe: &corev1.Probe{
|
||||
Handler: corev1.Handler{
|
||||
HTTPGet: &corev1.HTTPGetAction{
|
||||
Path: "/login",
|
||||
Port: intstr.FromString("http"),
|
||||
Scheme: corev1.URISchemeHTTP,
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: int32(100),
|
||||
TimeoutSeconds: int32(4),
|
||||
FailureThreshold: int32(12),
|
||||
SuccessThreshold: int32(1),
|
||||
PeriodSeconds: int32(1),
|
||||
},
|
||||
LivenessProbe: &corev1.Probe{
|
||||
Handler: corev1.Handler{
|
||||
HTTPGet: &corev1.HTTPGetAction{
|
||||
Path: "/login",
|
||||
Port: intstr.FromString("http"),
|
||||
Scheme: corev1.URISchemeHTTP,
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: int32(80),
|
||||
TimeoutSeconds: int32(4),
|
||||
FailureThreshold: int32(30),
|
||||
SuccessThreshold: int32(1),
|
||||
PeriodSeconds: int32(5),
|
||||
},
|
||||
VolumeMounts: []corev1.VolumeMount{
|
||||
{
|
||||
Name: "plugins-cache",
|
||||
MountPath: "/usr/share/jenkins/ref/plugins",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "envoyproxy",
|
||||
Image: "envoyproxy/envoy-alpine:v1.14.1",
|
||||
},
|
||||
},
|
||||
Plugins: []v1alpha2.Plugin{
|
||||
{Name: "audit-trail", Version: "3.10"},
|
||||
{Name: "simple-theme-plugin", Version: "0.7"},
|
||||
{Name: "github", Version: "1.34.1"},
|
||||
{Name: "devoptics", Version: "1.1934", DownloadURL: "https://jenkins-updates.cloudbees.com/download/plugins/devoptics/1.1934/devoptics.hpi"},
|
||||
},
|
||||
PriorityClassName: priorityClassName,
|
||||
NodeSelector: map[string]string{"kubernetes.io/os": "linux"},
|
||||
Volumes: []corev1.Volume{
|
||||
{
|
||||
Name: "plugins-cache",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
EmptyDir: &corev1.EmptyDirVolumeSource{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
SeedJobs: seedJobs,
|
||||
Service: v1alpha2.Service{
|
||||
Type: corev1.ServiceTypeNodePort,
|
||||
Port: constants.DefaultHTTPPortInt32,
|
||||
},
|
||||
},
|
||||
}
|
||||
jenkins.Spec.Roles = []rbacv1.RoleRef{
|
||||
{
|
||||
APIGroup: "rbac.authorization.k8s.io",
|
||||
Kind: "Role",
|
||||
Name: resources.GetResourceName(jenkins),
|
||||
},
|
||||
}
|
||||
updateJenkinsCR(jenkins)
|
||||
|
||||
_, _ = fmt.Fprintf(GinkgoWriter, "Jenkins CR %+v\n", *jenkins)
|
||||
|
||||
Expect(K8sClient.Create(context.TODO(), jenkins)).Should(Succeed())
|
||||
|
||||
return jenkins
|
||||
}
|
||||
|
||||
func createJenkinsCRSafeRestart(name, namespace string, seedJob *[]v1alpha2.SeedJob, groovyScripts v1alpha2.GroovyScripts, casc v1alpha2.ConfigurationAsCode, priorityClassName string) *v1alpha2.Jenkins {
|
||||
var seedJobs []v1alpha2.SeedJob
|
||||
if seedJob != nil {
|
||||
@@ -171,7 +66,8 @@ func createJenkinsCRSafeRestart(name, namespace string, seedJob *[]v1alpha2.Seed
|
||||
Annotations: map[string]string{"test": "label"},
|
||||
Containers: []v1alpha2.Container{
|
||||
{
|
||||
Name: resources.JenkinsMasterContainerName,
|
||||
Name: resources.JenkinsMasterContainerName,
|
||||
Image: JenkinsTestImage,
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
Name: "TEST_ENV",
|
||||
@@ -206,6 +102,16 @@ func createJenkinsCRSafeRestart(name, namespace string, seedJob *[]v1alpha2.Seed
|
||||
SuccessThreshold: int32(1),
|
||||
PeriodSeconds: int32(5),
|
||||
},
|
||||
Resources: corev1.ResourceRequirements{
|
||||
Requests: corev1.ResourceList{
|
||||
corev1.ResourceCPU: resource.MustParse("1"),
|
||||
corev1.ResourceMemory: resource.MustParse("500Mi"),
|
||||
},
|
||||
Limits: corev1.ResourceList{
|
||||
corev1.ResourceCPU: resource.MustParse("1000m"),
|
||||
corev1.ResourceMemory: resource.MustParse("3Gi"),
|
||||
},
|
||||
},
|
||||
VolumeMounts: []corev1.VolumeMount{
|
||||
{
|
||||
Name: "plugins-cache",
|
||||
|
||||
+4
-4
@@ -8,7 +8,6 @@ import (
|
||||
"sort"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/api/events/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
@@ -109,17 +108,18 @@ func printKubernetesEvents(namespace string) {
|
||||
_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Last %d events from kubernetes:\n", kubernetesEventsLimit)
|
||||
|
||||
for _, event := range events {
|
||||
_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "%+v\n\n", event)
|
||||
_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Event CreationTime: %s, Type: %s, Reason: %s, Object: %s %s/%s, Action: %s\n",
|
||||
event.CreationTimestamp, event.Type, event.Reason, event.Regarding.Kind, event.Regarding.Namespace, event.Regarding.Name, event.Note)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func printKubernetesPods(namespace string) {
|
||||
_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "All pods in '%s' namespace:\n", namespace)
|
||||
_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "\nAll pods in '%s' namespace:\n", namespace)
|
||||
|
||||
pod, err := getOperatorPod(namespace)
|
||||
if err == nil {
|
||||
_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "%+v\n\n", pod)
|
||||
_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "%s: %+v \n", pod.Name, pod.Status.Conditions)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,8 @@ func createJenkinsWithBackupAndRestoreConfigured(name, namespace string) *v1alph
|
||||
Master: v1alpha2.JenkinsMaster{
|
||||
Containers: []v1alpha2.Container{
|
||||
{
|
||||
Name: resources.JenkinsMasterContainerName,
|
||||
Name: resources.JenkinsMasterContainerName,
|
||||
Image: JenkinsTestImage,
|
||||
VolumeMounts: []corev1.VolumeMount{
|
||||
{
|
||||
Name: "plugins-cache",
|
||||
@@ -143,6 +144,16 @@ func createJenkinsWithBackupAndRestoreConfigured(name, namespace string) *v1alph
|
||||
SuccessThreshold: int32(1),
|
||||
PeriodSeconds: int32(5),
|
||||
},
|
||||
Resources: corev1.ResourceRequirements{
|
||||
Requests: corev1.ResourceList{
|
||||
corev1.ResourceCPU: resource.MustParse("1"),
|
||||
corev1.ResourceMemory: resource.MustParse("500Mi"),
|
||||
},
|
||||
Limits: corev1.ResourceList{
|
||||
corev1.ResourceCPU: resource.MustParse("1000m"),
|
||||
corev1.ResourceMemory: resource.MustParse("3Gi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: containerName,
|
||||
|
||||
@@ -5,15 +5,24 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
||||
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
"github.com/onsi/gomega"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/client-go/rest"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/envtest"
|
||||
)
|
||||
|
||||
const JenkinsTestImage = "jenkins/jenkins:2.303.2-lts"
|
||||
|
||||
var (
|
||||
Cfg *rest.Config
|
||||
K8sClient client.Client
|
||||
@@ -59,3 +68,113 @@ func DestroyNamespace(namespace *corev1.Namespace) {
|
||||
return !exists, nil
|
||||
}, time.Second*120, time.Second).Should(gomega.BeTrue())
|
||||
}
|
||||
|
||||
func RenderJenkinsCR(name, namespace string, seedJob *[]v1alpha2.SeedJob, groovyScripts v1alpha2.GroovyScripts, casc v1alpha2.ConfigurationAsCode, priorityClassName string) *v1alpha2.Jenkins {
|
||||
var seedJobs []v1alpha2.SeedJob
|
||||
if seedJob != nil {
|
||||
seedJobs = append(seedJobs, *seedJob...)
|
||||
}
|
||||
|
||||
return &v1alpha2.Jenkins{
|
||||
TypeMeta: v1alpha2.JenkinsTypeMeta(),
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: v1alpha2.JenkinsSpec{
|
||||
GroovyScripts: groovyScripts,
|
||||
ConfigurationAsCode: casc,
|
||||
Master: v1alpha2.JenkinsMaster{
|
||||
Annotations: map[string]string{"test": "label"},
|
||||
Containers: []v1alpha2.Container{
|
||||
{
|
||||
Name: resources.JenkinsMasterContainerName,
|
||||
Image: JenkinsTestImage,
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
Name: "TEST_ENV",
|
||||
Value: "test_env_value",
|
||||
},
|
||||
},
|
||||
ReadinessProbe: &corev1.Probe{
|
||||
Handler: corev1.Handler{
|
||||
HTTPGet: &corev1.HTTPGetAction{
|
||||
Path: "/login",
|
||||
Port: intstr.FromString("http"),
|
||||
Scheme: corev1.URISchemeHTTP,
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: int32(100),
|
||||
TimeoutSeconds: int32(4),
|
||||
FailureThreshold: int32(12),
|
||||
SuccessThreshold: int32(1),
|
||||
PeriodSeconds: int32(1),
|
||||
},
|
||||
LivenessProbe: &corev1.Probe{
|
||||
Handler: corev1.Handler{
|
||||
HTTPGet: &corev1.HTTPGetAction{
|
||||
Path: "/login",
|
||||
Port: intstr.FromString("http"),
|
||||
Scheme: corev1.URISchemeHTTP,
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: int32(80),
|
||||
TimeoutSeconds: int32(4),
|
||||
FailureThreshold: int32(30),
|
||||
SuccessThreshold: int32(1),
|
||||
PeriodSeconds: int32(5),
|
||||
},
|
||||
Resources: corev1.ResourceRequirements{
|
||||
Requests: corev1.ResourceList{
|
||||
corev1.ResourceCPU: resource.MustParse("1"),
|
||||
corev1.ResourceMemory: resource.MustParse("500Mi"),
|
||||
},
|
||||
Limits: corev1.ResourceList{
|
||||
corev1.ResourceCPU: resource.MustParse("1000m"),
|
||||
corev1.ResourceMemory: resource.MustParse("3Gi"),
|
||||
},
|
||||
},
|
||||
VolumeMounts: []corev1.VolumeMount{
|
||||
{
|
||||
Name: "plugins-cache",
|
||||
MountPath: "/usr/share/jenkins/ref/plugins",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "envoyproxy",
|
||||
Image: "envoyproxy/envoy-alpine:v1.14.1",
|
||||
},
|
||||
},
|
||||
Plugins: []v1alpha2.Plugin{
|
||||
{Name: "audit-trail", Version: "3.10"},
|
||||
{Name: "simple-theme-plugin", Version: "0.7"},
|
||||
{Name: "github", Version: "1.34.1"},
|
||||
{Name: "devoptics", Version: "1.1934", DownloadURL: "https://jenkins-updates.cloudbees.com/download/plugins/devoptics/1.1934/devoptics.hpi"},
|
||||
},
|
||||
PriorityClassName: priorityClassName,
|
||||
NodeSelector: map[string]string{"kubernetes.io/os": "linux"},
|
||||
Volumes: []corev1.Volume{
|
||||
{
|
||||
Name: "plugins-cache",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
EmptyDir: &corev1.EmptyDirVolumeSource{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
SeedJobs: seedJobs,
|
||||
Service: v1alpha2.Service{
|
||||
Type: corev1.ServiceTypeNodePort,
|
||||
Port: constants.DefaultHTTPPortInt32,
|
||||
},
|
||||
Roles: []rbacv1.RoleRef{
|
||||
{
|
||||
APIGroup: "rbac.authorization.k8s.io",
|
||||
Kind: "Role",
|
||||
Name: "jenkins-operator-jenkins",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
+67
-155
@@ -7,20 +7,18 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
||||
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
||||
"github.com/jenkinsci/kubernetes-operator/test/e2e"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
// +kubebuilder:scaffold:imports
|
||||
)
|
||||
|
||||
var _ = Describe("Jenkins Controller with webhook", func() {
|
||||
const jenkinsCRName = "jenkins"
|
||||
|
||||
var _ = Describe("Jenkins Controller", func() {
|
||||
var (
|
||||
namespace *corev1.Namespace
|
||||
)
|
||||
@@ -42,14 +40,15 @@ var _ = Describe("Jenkins Controller with webhook", func() {
|
||||
jenkins := &v1alpha2.Jenkins{
|
||||
TypeMeta: v1alpha2.JenkinsTypeMeta(),
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "jenkins",
|
||||
Name: jenkinsCRName,
|
||||
Namespace: namespace.Name,
|
||||
},
|
||||
}
|
||||
|
||||
cmd := exec.Command("../../bin/helm", "upgrade", "jenkins", "../../chart/jenkins-operator", "--namespace", namespace.Name, "--debug",
|
||||
"--set-string", fmt.Sprintf("jenkins.namespace=%s", namespace.Name),
|
||||
"--set-string", fmt.Sprintf("operator.image=%s", *imageName), "--install", "--wait")
|
||||
"--set-string", fmt.Sprintf("jenkins.image=%s", "jenkins/jenkins:2.303.2-lts"),
|
||||
"--set-string", fmt.Sprintf("operator.image=%s", *imageName), "--install")
|
||||
output, err := cmd.CombinedOutput()
|
||||
Expect(err).NotTo(HaveOccurred(), string(output))
|
||||
|
||||
@@ -58,47 +57,77 @@ var _ = Describe("Jenkins Controller with webhook", func() {
|
||||
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Context("Deploys jenkins operator with helm charts with validating webhook and jenkins instance disabled", func() {
|
||||
It("Deploys operator,denies creating a jenkins cr and creates jenkins cr with validation turned off", func() {
|
||||
var _ = Describe("Jenkins Controller with security validator", func() {
|
||||
|
||||
var (
|
||||
namespace *corev1.Namespace
|
||||
seedJobs = &[]v1alpha2.SeedJob{}
|
||||
groovyScripts = v1alpha2.GroovyScripts{
|
||||
Customization: v1alpha2.Customization{
|
||||
Configurations: []v1alpha2.ConfigMapRef{},
|
||||
},
|
||||
}
|
||||
casc = v1alpha2.ConfigurationAsCode{
|
||||
Customization: v1alpha2.Customization{
|
||||
Configurations: []v1alpha2.ConfigMapRef{},
|
||||
},
|
||||
}
|
||||
invalidPlugins = []v1alpha2.Plugin{
|
||||
{Name: "simple-theme-plugin", Version: "0.6"},
|
||||
{Name: "audit-trail", Version: "3.5"},
|
||||
{Name: "github", Version: "1.29.0"},
|
||||
}
|
||||
validPlugins = []v1alpha2.Plugin{
|
||||
{Name: "simple-theme-plugin", Version: "0.6"},
|
||||
{Name: "audit-trail", Version: "3.8"},
|
||||
{Name: "github", Version: "1.31.0"},
|
||||
}
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
namespace = e2e.CreateNamespace()
|
||||
})
|
||||
AfterEach(func() {
|
||||
cmd := exec.Command("../../bin/helm", "delete", "jenkins", "--namespace", namespace.Name)
|
||||
output, err := cmd.CombinedOutput()
|
||||
Expect(err).NotTo(HaveOccurred(), string(output))
|
||||
|
||||
e2e.ShowLogsIfTestHasFailed(CurrentGinkgoTestDescription().Failed, namespace.Name)
|
||||
e2e.DestroyNamespace(namespace)
|
||||
})
|
||||
|
||||
Context("When Jenkins CR contains plugins with security warnings", func() {
|
||||
It("Denies creating a jenkins CR with a warning", func() {
|
||||
By("Deploying the operator along with webhook and cert-manager")
|
||||
cmd := exec.Command("../../bin/helm", "upgrade", "jenkins", "../../chart/jenkins-operator", "--namespace", namespace.Name, "--debug",
|
||||
"--set-string", fmt.Sprintf("jenkins.namespace=%s", namespace.Name), "--set-string", fmt.Sprintf("operator.image=%s", *imageName),
|
||||
"--set", fmt.Sprintf("webhook.enabled=%t", true), "--set", fmt.Sprintf("jenkins.enabled=%t", false), "--install", "--wait")
|
||||
"--set-string", fmt.Sprintf("jenkins.namespace=%s", namespace.Name),
|
||||
"--set-string", fmt.Sprintf("operator.image=%s", *imageName),
|
||||
"--set", fmt.Sprintf("jenkins.securityValidator=%t", true),
|
||||
"--set", fmt.Sprintf("jenkins.enabled=%t", false),
|
||||
"--set", fmt.Sprintf("webhook.enabled=%t", true), "--install")
|
||||
output, err := cmd.CombinedOutput()
|
||||
Expect(err).NotTo(HaveOccurred(), string(output))
|
||||
|
||||
By("Waiting for the operator to fetch the plugin data ")
|
||||
By("Waiting for the operator to fetch the plugin data")
|
||||
time.Sleep(time.Duration(200) * time.Second)
|
||||
|
||||
By("Denying a create request for a Jenkins custom resource with some plugins having security warnings and validation is turned on")
|
||||
userplugins := []v1alpha2.Plugin{
|
||||
{Name: "simple-theme-plugin", Version: "0.6"},
|
||||
{Name: "audit-trail", Version: "3.5"},
|
||||
{Name: "github", Version: "1.29.0"},
|
||||
}
|
||||
jenkins := CreateJenkinsCR("jenkins", namespace.Name, userplugins, true)
|
||||
By("Denying a create request for a Jenkins custom resource")
|
||||
jenkins := e2e.RenderJenkinsCR(jenkinsCRName, namespace.Name, seedJobs, groovyScripts, casc, "")
|
||||
jenkins.Spec.Master.Plugins = invalidPlugins
|
||||
jenkins.Spec.ValidateSecurityWarnings = true
|
||||
Expect(e2e.K8sClient.Create(context.TODO(), jenkins)).Should(MatchError("admission webhook \"vjenkins.kb.io\" denied the request: security vulnerabilities detected in the following user-defined plugins: \naudit-trail:3.5\ngithub:1.29.0"))
|
||||
|
||||
By("Creating the Jenkins resource with plugins not having any security warnings and validation is turned on")
|
||||
userplugins = []v1alpha2.Plugin{
|
||||
{Name: "simple-theme-plugin", Version: "0.6"},
|
||||
{Name: "audit-trail", Version: "3.8"},
|
||||
{Name: "github", Version: "1.31.0"},
|
||||
}
|
||||
jenkins = CreateJenkinsCR("jenkins", namespace.Name, userplugins, true)
|
||||
Expect(e2e.K8sClient.Create(context.TODO(), jenkins)).Should(Succeed())
|
||||
e2e.WaitForJenkinsBaseConfigurationToComplete(jenkins)
|
||||
e2e.WaitForJenkinsUserConfigurationToComplete(jenkins)
|
||||
|
||||
})
|
||||
|
||||
It("Deploys operator, creates a jenkins cr and denies update request for another one", func() {
|
||||
})
|
||||
Context("When Jenkins CR doesn't contain plugins with security warnings", func() {
|
||||
It("Jenkins instance is successfully created", func() {
|
||||
By("Deploying the operator along with webhook and cert-manager")
|
||||
cmd := exec.Command("../../bin/helm", "upgrade", "jenkins", "../../chart/jenkins-operator", "--namespace", namespace.Name, "--debug",
|
||||
"--set-string", fmt.Sprintf("jenkins.namespace=%s", namespace.Name), "--set-string", fmt.Sprintf("operator.image=%s", *imageName),
|
||||
"--set", fmt.Sprintf("webhook.enabled=%t", true), "--set", fmt.Sprintf("jenkins.enabled=%t", false), "--install", "--wait")
|
||||
"--set-string", fmt.Sprintf("jenkins.namespace=%s", namespace.Name),
|
||||
"--set-string", fmt.Sprintf("operator.image=%s", *imageName),
|
||||
"--set", fmt.Sprintf("webhook.enabled=%t", true),
|
||||
"--set", fmt.Sprintf("jenkins.enabled=%t", false), "--install")
|
||||
output, err := cmd.CombinedOutput()
|
||||
Expect(err).NotTo(HaveOccurred(), string(output))
|
||||
|
||||
@@ -106,129 +135,12 @@ var _ = Describe("Jenkins Controller with webhook", func() {
|
||||
time.Sleep(time.Duration(200) * time.Second)
|
||||
|
||||
By("Creating a Jenkins custom resource with some plugins having security warnings but validation is turned off")
|
||||
userplugins := []v1alpha2.Plugin{
|
||||
{Name: "simple-theme-plugin", Version: "0.6"},
|
||||
{Name: "audit-trail", Version: "3.5"},
|
||||
{Name: "github", Version: "1.29.0"},
|
||||
}
|
||||
jenkins := CreateJenkinsCR("jenkins", namespace.Name, userplugins, false)
|
||||
jenkins := e2e.RenderJenkinsCR(jenkinsCRName, namespace.Name, seedJobs, groovyScripts, casc, "")
|
||||
jenkins.Spec.Master.Plugins = validPlugins
|
||||
jenkins.Spec.ValidateSecurityWarnings = true
|
||||
Expect(e2e.K8sClient.Create(context.TODO(), jenkins)).Should(Succeed())
|
||||
e2e.WaitForJenkinsBaseConfigurationToComplete(jenkins)
|
||||
e2e.WaitForJenkinsUserConfigurationToComplete(jenkins)
|
||||
|
||||
By("Failing to update the Jenkins custom resource because some plugins have security warnings and validation is turned on")
|
||||
userplugins = []v1alpha2.Plugin{
|
||||
{Name: "vncviewer", Version: "1.7"},
|
||||
{Name: "build-timestamp", Version: "1.0.3"},
|
||||
{Name: "deployit-plugin", Version: "7.5.5"},
|
||||
{Name: "github-branch-source", Version: "2.0.7"},
|
||||
{Name: "aws-lambda-cloud", Version: "0.4"},
|
||||
{Name: "groovy", Version: "1.31"},
|
||||
{Name: "google-login", Version: "1.2"},
|
||||
}
|
||||
jenkins.Spec.Master.Plugins = userplugins
|
||||
jenkins.Spec.ValidateSecurityWarnings = true
|
||||
Expect(e2e.K8sClient.Update(context.TODO(), jenkins)).Should(MatchError("admission webhook \"vjenkins.kb.io\" denied the request: security vulnerabilities detected in the following user-defined plugins: \nvncviewer:1.7\ndeployit-plugin:7.5.5\ngithub-branch-source:2.0.7\ngroovy:1.31\ngoogle-login:1.2"))
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
func CreateJenkinsCR(name string, namespace string, userPlugins []v1alpha2.Plugin, validateSecurityWarnings bool) *v1alpha2.Jenkins {
|
||||
jenkins := &v1alpha2.Jenkins{
|
||||
TypeMeta: v1alpha2.JenkinsTypeMeta(),
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: v1alpha2.JenkinsSpec{
|
||||
GroovyScripts: v1alpha2.GroovyScripts{
|
||||
Customization: v1alpha2.Customization{
|
||||
Configurations: []v1alpha2.ConfigMapRef{},
|
||||
Secret: v1alpha2.SecretRef{
|
||||
Name: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
ConfigurationAsCode: v1alpha2.ConfigurationAsCode{
|
||||
Customization: v1alpha2.Customization{
|
||||
Configurations: []v1alpha2.ConfigMapRef{},
|
||||
Secret: v1alpha2.SecretRef{
|
||||
Name: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
Master: v1alpha2.JenkinsMaster{
|
||||
Containers: []v1alpha2.Container{
|
||||
{
|
||||
Name: resources.JenkinsMasterContainerName,
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
Name: "TEST_ENV",
|
||||
Value: "test_env_value",
|
||||
},
|
||||
},
|
||||
ReadinessProbe: &corev1.Probe{
|
||||
Handler: corev1.Handler{
|
||||
HTTPGet: &corev1.HTTPGetAction{
|
||||
Path: "/login",
|
||||
Port: intstr.FromString("http"),
|
||||
Scheme: corev1.URISchemeHTTP,
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: int32(100),
|
||||
TimeoutSeconds: int32(4),
|
||||
FailureThreshold: int32(40),
|
||||
SuccessThreshold: int32(1),
|
||||
PeriodSeconds: int32(10),
|
||||
},
|
||||
LivenessProbe: &corev1.Probe{
|
||||
Handler: corev1.Handler{
|
||||
HTTPGet: &corev1.HTTPGetAction{
|
||||
Path: "/login",
|
||||
Port: intstr.FromString("http"),
|
||||
Scheme: corev1.URISchemeHTTP,
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: int32(80),
|
||||
TimeoutSeconds: int32(4),
|
||||
FailureThreshold: int32(30),
|
||||
SuccessThreshold: int32(1),
|
||||
PeriodSeconds: int32(5),
|
||||
},
|
||||
VolumeMounts: []corev1.VolumeMount{
|
||||
{
|
||||
Name: "plugins-cache",
|
||||
MountPath: "/usr/share/jenkins/ref/plugins",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "envoyproxy",
|
||||
Image: "envoyproxy/envoy-alpine:v1.14.1",
|
||||
},
|
||||
},
|
||||
Plugins: userPlugins,
|
||||
DisableCSRFProtection: false,
|
||||
NodeSelector: map[string]string{"kubernetes.io/os": "linux"},
|
||||
Volumes: []corev1.Volume{
|
||||
{
|
||||
Name: "plugins-cache",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
EmptyDir: &corev1.EmptyDirVolumeSource{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ValidateSecurityWarnings: validateSecurityWarnings,
|
||||
Service: v1alpha2.Service{
|
||||
Type: corev1.ServiceTypeNodePort,
|
||||
Port: constants.DefaultHTTPPortInt32,
|
||||
},
|
||||
JenkinsAPISettings: v1alpha2.JenkinsAPISettings{AuthorizationStrategy: v1alpha2.CreateUserAuthorizationStrategy},
|
||||
},
|
||||
}
|
||||
|
||||
return jenkins
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user