Skip to content
Snippets Groups Projects
Commit f253ea6a authored by Tomasz Maczukin's avatar Tomasz Maczukin
Browse files

Merge branch 'master' into 'master'

adding support for kubernetes service account and override on gitlab-ci.yaml

See merge request !554
parents 551d36c9 9dfa302f
No related branches found
No related tags found
No related merge requests found
......@@ -119,34 +119,36 @@ func (p KubernetesPullPolicy) Get() (KubernetesPullPolicy, error) {
}
type KubernetesConfig struct {
Host string `toml:"host" json:"host" long:"host" env:"KUBERNETES_HOST" description:"Optional Kubernetes master host URL (auto-discovery attempted if not specified)"`
CertFile string `toml:"cert_file,omitempty" json:"cert_file" long:"cert-file" env:"KUBERNETES_CERT_FILE" description:"Optional Kubernetes master auth certificate"`
KeyFile string `toml:"key_file,omitempty" json:"key_file" long:"key-file" env:"KUBERNETES_KEY_FILE" description:"Optional Kubernetes master auth private key"`
CAFile string `toml:"ca_file,omitempty" json:"ca_file" long:"ca-file" env:"KUBERNETES_CA_FILE" description:"Optional Kubernetes master auth ca certificate"`
Image string `toml:"image" json:"image" long:"image" env:"KUBERNETES_IMAGE" description:"Default docker image to use for builds when none is specified"`
Namespace string `toml:"namespace" json:"namespace" long:"namespace" env:"KUBERNETES_NAMESPACE" description:"Namespace to run Kubernetes jobs in"`
NamespaceOverwriteAllowed string `toml:"namespace_overwrite_allowed" json:"namespace_overwrite_allowed" long:"namespace_overwrite_allowed" env:"KUBERNETES_NAMESPACE_OVERWRITE_ALLOWED" description:"Regex to validate 'KUBERNETES_NAMESPACE_OVERWRITE' value"`
Privileged bool `toml:"privileged,omitzero" json:"privileged" long:"privileged" env:"KUBERNETES_PRIVILEGED" description:"Run all containers with the privileged flag enabled"`
CPULimit string `toml:"cpu_limit,omitempty" json:"cpu_limit" long:"cpu-limit" env:"KUBERNETES_CPU_LIMIT" description:"The CPU allocation given to build containers"`
MemoryLimit string `toml:"memory_limit,omitempty" json:"memory_limit" long:"memory-limit" env:"KUBERNETES_MEMORY_LIMIT" description:"The amount of memory allocated to build containers"`
ServiceCPULimit string `toml:"service_cpu_limit,omitempty" json:"service_cpu_limit" long:"service-cpu-limit" env:"KUBERNETES_SERVICE_CPU_LIMIT" description:"The CPU allocation given to build service containers"`
ServiceMemoryLimit string `toml:"service_memory_limit,omitempty" json:"service_memory_limit" long:"service-memory-limit" env:"KUBERNETES_SERVICE_MEMORY_LIMIT" description:"The amount of memory allocated to build service containers"`
HelperCPULimit string `toml:"helper_cpu_limit,omitempty" json:"helper_cpu_limit" long:"helper-cpu-limit" env:"KUBERNETES_HELPER_CPU_LIMIT" description:"The CPU allocation given to build helper containers"`
HelperMemoryLimit string `toml:"helper_memory_limit,omitempty" json:"helper_memory_limit" long:"helper-memory-limit" env:"KUBERNETES_HELPER_MEMORY_LIMIT" description:"The amount of memory allocated to build helper containers"`
CPURequest string `toml:"cpu_request,omitempty" json:"cpu_request" long:"cpu-request" env:"KUBERNETES_CPU_REQUEST" description:"The CPU allocation requested for build containers"`
MemoryRequest string `toml:"memory_request,omitempty" json:"memory_request" long:"memory-request" env:"KUBERNETES_MEMORY_REQUEST" description:"The amount of memory requested from build containers"`
ServiceCPURequest string `toml:"service_cpu_request,omitempty" json:"service_cpu_request" long:"service-cpu-request" env:"KUBERNETES_SERVICE_CPU_REQUEST" description:"The CPU allocation requested for build service containers"`
ServiceMemoryRequest string `toml:"service_memory_request,omitempty" json:"service_memory_request" long:"service-memory-request" env:"KUBERNETES_SERVICE_MEMORY_REQUEST" description:"The amount of memory requested for build service containers"`
HelperCPURequest string `toml:"helper_cpu_request,omitempty" json:"helper_cpu_request" long:"helper-cpu-request" env:"KUBERNETES_HELPER_CPU_REQUEST" description:"The CPU allocation requested for build helper containers"`
HelperMemoryRequest string `toml:"helper_memory_request,omitempty" json:"helper_memory_request" long:"helper-memory-request" env:"KUBERNETES_HELPER_MEMORY_REQUEST" description:"The amount of memory requested for build helper containers"`
PullPolicy KubernetesPullPolicy `toml:"pull_policy,omitempty" json:"pull_policy" long:"pull-policy" env:"KUBERNETES_PULL_POLICY" description:"Policy for if/when to pull a container image (never, if-not-present, always). The cluster default will be used if not set"`
NodeSelector map[string]string `toml:"node_selector,omitempty" json:"node_selector" long:"node-selector" description:"A toml table/json object of key=value. Value is expected to be a string. When set this will create pods on k8s nodes that match all the key=value pairs."`
ImagePullSecrets []string `toml:"image_pull_secrets,omitempty" json:"image_pull_secrets" long:"image-pull-secrets" env:"KUBERNETES_IMAGE_PULL_SECRETS" description:"A list of image pull secrets that are used for pulling docker image"`
HelperImage string `toml:"helper_image,omitempty" json:"helper_image" long:"helper-image" env:"KUBERNETES_HELPER_IMAGE" description:"[ADVANCED] Override the default helper image used to clone repos and upload artifacts"`
TerminationGracePeriodSeconds int64 `toml:"terminationGracePeriodSeconds,omitzero" json:"terminationGracePeriodSeconds" long:"terminationGracePeriodSeconds" env:"KUBERNETES_TERMINATIONGRACEPERIODSECONDS" description:"Duration after the processes running in the pod are sent a termination signal and the time when the processes are forcibly halted with a kill signal."`
PollInterval int `toml:"poll_interval,omitzero" json:"poll_interval" long:"poll-interval" env:"KUBERNETES_POLL_INTERVAL" description:"How frequently, in seconds, the runner will poll the Kubernetes pod it has just created to check its status"`
PollTimeout int `toml:"poll_timeout,omitzero" json:"poll_timeout" long:"poll-timeout" env:"KUBERNETES_POLL_TIMEOUT" description:"The total amount of time, in seconds, that needs to pass before the runner will timeout attempting to connect to the pod it has just created (useful for queueing more builds that the cluster can handle at a time)"`
PodLabels map[string]string `toml:"pod_labels,omitempty" json:"pod_labels" long:"pod-labels" description:"A toml table/json object of key-value. Value is expected to be a string. When set, this will create pods with the given pod labels. Environment variables will be substituted for values here."`
Host string `toml:"host" json:"host" long:"host" env:"KUBERNETES_HOST" description:"Optional Kubernetes master host URL (auto-discovery attempted if not specified)"`
CertFile string `toml:"cert_file,omitempty" json:"cert_file" long:"cert-file" env:"KUBERNETES_CERT_FILE" description:"Optional Kubernetes master auth certificate"`
KeyFile string `toml:"key_file,omitempty" json:"key_file" long:"key-file" env:"KUBERNETES_KEY_FILE" description:"Optional Kubernetes master auth private key"`
CAFile string `toml:"ca_file,omitempty" json:"ca_file" long:"ca-file" env:"KUBERNETES_CA_FILE" description:"Optional Kubernetes master auth ca certificate"`
Image string `toml:"image" json:"image" long:"image" env:"KUBERNETES_IMAGE" description:"Default docker image to use for builds when none is specified"`
Namespace string `toml:"namespace" json:"namespace" long:"namespace" env:"KUBERNETES_NAMESPACE" description:"Namespace to run Kubernetes jobs in"`
NamespaceOverwriteAllowed string `toml:"namespace_overwrite_allowed" json:"namespace_overwrite_allowed" long:"namespace_overwrite_allowed" env:"KUBERNETES_NAMESPACE_OVERWRITE_ALLOWED" description:"Regex to validate 'KUBERNETES_NAMESPACE_OVERWRITE' value"`
Privileged bool `toml:"privileged,omitzero" json:"privileged" long:"privileged" env:"KUBERNETES_PRIVILEGED" description:"Run all containers with the privileged flag enabled"`
CPULimit string `toml:"cpu_limit,omitempty" json:"cpu_limit" long:"cpu-limit" env:"KUBERNETES_CPU_LIMIT" description:"The CPU allocation given to build containers"`
MemoryLimit string `toml:"memory_limit,omitempty" json:"memory_limit" long:"memory-limit" env:"KUBERNETES_MEMORY_LIMIT" description:"The amount of memory allocated to build containers"`
ServiceCPULimit string `toml:"service_cpu_limit,omitempty" json:"service_cpu_limit" long:"service-cpu-limit" env:"KUBERNETES_SERVICE_CPU_LIMIT" description:"The CPU allocation given to build service containers"`
ServiceMemoryLimit string `toml:"service_memory_limit,omitempty" json:"service_memory_limit" long:"service-memory-limit" env:"KUBERNETES_SERVICE_MEMORY_LIMIT" description:"The amount of memory allocated to build service containers"`
HelperCPULimit string `toml:"helper_cpu_limit,omitempty" json:"helper_cpu_limit" long:"helper-cpu-limit" env:"KUBERNETES_HELPER_CPU_LIMIT" description:"The CPU allocation given to build helper containers"`
HelperMemoryLimit string `toml:"helper_memory_limit,omitempty" json:"helper_memory_limit" long:"helper-memory-limit" env:"KUBERNETES_HELPER_MEMORY_LIMIT" description:"The amount of memory allocated to build helper containers"`
CPURequest string `toml:"cpu_request,omitempty" json:"cpu_request" long:"cpu-request" env:"KUBERNETES_CPU_REQUEST" description:"The CPU allocation requested for build containers"`
MemoryRequest string `toml:"memory_request,omitempty" json:"memory_request" long:"memory-request" env:"KUBERNETES_MEMORY_REQUEST" description:"The amount of memory requested from build containers"`
ServiceCPURequest string `toml:"service_cpu_request,omitempty" json:"service_cpu_request" long:"service-cpu-request" env:"KUBERNETES_SERVICE_CPU_REQUEST" description:"The CPU allocation requested for build service containers"`
ServiceMemoryRequest string `toml:"service_memory_request,omitempty" json:"service_memory_request" long:"service-memory-request" env:"KUBERNETES_SERVICE_MEMORY_REQUEST" description:"The amount of memory requested for build service containers"`
HelperCPURequest string `toml:"helper_cpu_request,omitempty" json:"helper_cpu_request" long:"helper-cpu-request" env:"KUBERNETES_HELPER_CPU_REQUEST" description:"The CPU allocation requested for build helper containers"`
HelperMemoryRequest string `toml:"helper_memory_request,omitempty" json:"helper_memory_request" long:"helper-memory-request" env:"KUBERNETES_HELPER_MEMORY_REQUEST" description:"The amount of memory requested for build helper containers"`
PullPolicy KubernetesPullPolicy `toml:"pull_policy,omitempty" json:"pull_policy" long:"pull-policy" env:"KUBERNETES_PULL_POLICY" description:"Policy for if/when to pull a container image (never, if-not-present, always). The cluster default will be used if not set"`
NodeSelector map[string]string `toml:"node_selector,omitempty" json:"node_selector" long:"node-selector" description:"A toml table/json object of key=value. Value is expected to be a string. When set this will create pods on k8s nodes that match all the key=value pairs."`
ImagePullSecrets []string `toml:"image_pull_secrets,omitempty" json:"image_pull_secrets" long:"image-pull-secrets" env:"KUBERNETES_IMAGE_PULL_SECRETS" description:"A list of image pull secrets that are used for pulling docker image"`
HelperImage string `toml:"helper_image,omitempty" json:"helper_image" long:"helper-image" env:"KUBERNETES_HELPER_IMAGE" description:"[ADVANCED] Override the default helper image used to clone repos and upload artifacts"`
TerminationGracePeriodSeconds int64 `toml:"terminationGracePeriodSeconds,omitzero" json:"terminationGracePeriodSeconds" long:"terminationGracePeriodSeconds" env:"KUBERNETES_TERMINATIONGRACEPERIODSECONDS" description:"Duration after the processes running in the pod are sent a termination signal and the time when the processes are forcibly halted with a kill signal."`
PollInterval int `toml:"poll_interval,omitzero" json:"poll_interval" long:"poll-interval" env:"KUBERNETES_POLL_INTERVAL" description:"How frequently, in seconds, the runner will poll the Kubernetes pod it has just created to check its status"`
PollTimeout int `toml:"poll_timeout,omitzero" json:"poll_timeout" long:"poll-timeout" env:"KUBERNETES_POLL_TIMEOUT" description:"The total amount of time, in seconds, that needs to pass before the runner will timeout attempting to connect to the pod it has just created (useful for queueing more builds that the cluster can handle at a time)"`
PodLabels map[string]string `toml:"pod_labels,omitempty" json:"pod_labels" long:"pod-labels" description:"A toml table/json object of key-value. Value is expected to be a string. When set, this will create pods with the given pod labels. Environment variables will be substituted for values here."`
ServiceAccount string `toml:"service_account,omitempty" json:"service_account" long:"service-account" env:"KUBERNETES_SERVICE_ACCOUNT" description:"Executor pods will use this Service Account to talk to kubernetes API"`
ServiceAccountOverwriteAllowed string `toml:"service_account_overwrite_allowed" json:"service_account_overwrite_allowed" long:"service_account_overwrite_allowed" env:"KUBERNETES_SERVICE_ACCOUNT_OVERWRITE_ALLOWED" description:"Regex to validate 'KUBERNETES_SERVICE_ACCOUNT' value"`
}
type RunnerCredentials struct {
......
......@@ -6,7 +6,7 @@ possible with the use of the **Kubernetes** executor.
The **Kubernetes** executor, when used with GitLab CI, connects to the Kubernetes
API in the cluster creating a Pod for each GitLab CI Job. This Pod is made
up of, at the very least, a build container and an additional container for each
`service` defined by the GitLab CI yaml. The names for these containers
`service` defined by the GitLab CI yaml. The names for these containers
are as follows:
- The build container is `build`
......@@ -73,6 +73,14 @@ The following keywords help to define the behaviour of the Runner within Kuberne
- `poll_interval`: How frequently, in seconds, the runner will poll the Kubernetes pod it has just created to check its status. [Default: 3]
- `poll_timeout`: The amount of time, in seconds, that needs to pass before the runner will timeout attempting to connect to the container it has just created (useful for queueing more builds that the cluster can handle at a time) [Default: 180]
- `pod_labels`: A set of labels to be added to each build pod created by the runner. The value of these can include environment variables for expansion.
- `service-account`: default service account to be used for making kubernetes api calls.
- `service_account_overwrite_allowed`: Regular expression to validate the contents of
the service account overwrite environment variable. When empty,
it disables the service account overwrite feature
### Configuring executor Service Account
You can set the `KUBERNETES_SERVICE_ACCOUNT` environment variable or use `--service-account` flag
### Overwriting Kubernetes Namespace
......@@ -92,6 +100,23 @@ Furthermore, to ensure only designated namespaces will be used during CI runs, i
`namespace_overwrite_allowed` with proper regular expression. When left empty the overwrite behaviour is
disabled.
### Overwriting Kubernetes Default Service Account
Additionally, Kubernetes service account can be overwritten on `.gitlab-ci.yml` file, by using the variable
`KUBERNETES_SERVICE_ACCOUNT_OVERWRITE`.
This approach allow you to specify a service account that is attached to the namespace, usefull when dealing
with complex RBAC configurations.
``` yaml
variables:
KUBERNETES_SERVICE_ACCOUNT_OVERWRITE: ci-service-account
```
usefull when overwritting the namespace and RBAC is setup in the cluster.
To ensure only designated service accounts will be used during CI runs, inform the configuration
`service_account_overwrite_allowed` or set the environment variable `KUBERNETES_SERVICE_ACCOUNT_OVERWRITE_ALLOWED`
with proper regular expression. When left empty the overwrite behaviour is disabled.
## Define keywords in the config toml
Each of the keywords can be defined in the `config.toml` for the gitlab runner.
......@@ -163,7 +188,7 @@ to contact the docker daemon in the other container be sure to include
Do *not* try to use an image that doesn't supply git and add the `GIT_STRATEGY=none`
environment variable for a job that you think doesn't need to do a fetch or clone.
Because Pods are ephemeral and do not keep state of previously run jobs your
checked out code will not exist in both the build and the docker service container.
checked out code will not exist in both the build and the docker service container.
Error's you might run into are things like `could not find git binary` and
the docker service complaining that it cannot follow some symlinks into your
build context because of the missing code.
......
......@@ -40,15 +40,15 @@ type executor struct {
credentials *api.Secret
options *kubernetesOptions
namespaceOverwrite string
buildLimits api.ResourceList
serviceLimits api.ResourceList
helperLimits api.ResourceList
buildRequests api.ResourceList
serviceRequests api.ResourceList
helperRequests api.ResourceList
pullPolicy common.KubernetesPullPolicy
namespaceOverwrite string
serviceAccountOverwrite string
buildLimits api.ResourceList
serviceLimits api.ResourceList
helperLimits api.ResourceList
buildRequests api.ResourceList
serviceRequests api.ResourceList
helperRequests api.ResourceList
pullPolicy common.KubernetesPullPolicy
}
func (s *executor) setupResources() error {
......@@ -79,7 +79,6 @@ func (s *executor) setupResources() error {
if s.helperRequests, err = limits(s.Config.Kubernetes.HelperCPURequest, s.Config.Kubernetes.HelperMemoryRequest); err != nil {
return fmt.Errorf("invalid helper requests specified: %s", err.Error())
}
return nil
}
......@@ -108,6 +107,10 @@ func (s *executor) Prepare(options common.ExecutorPrepareOptions) (err error) {
return err
}
if err = s.overwriteServiceAccount(options.Build); err != nil {
return err
}
s.prepareOptions(options.Build)
if err = s.checkDefaults(); err != nil {
......@@ -261,7 +264,6 @@ func (s *executor) setupBuildPod() error {
}
buildImage := s.Build.GetAllVariables().ExpandValue(s.options.Image)
pod, err := s.kubeClient.Pods(s.Config.Kubernetes.Namespace).Create(&api.Pod{
ObjectMeta: api.ObjectMeta{
GenerateName: s.Build.ProjectUniqueName(),
......@@ -277,8 +279,9 @@ func (s *executor) setupBuildPod() error {
},
},
},
RestartPolicy: api.RestartPolicyNever,
NodeSelector: s.Config.Kubernetes.NodeSelector,
ServiceAccountName: s.Config.Kubernetes.ServiceAccount,
RestartPolicy: api.RestartPolicyNever,
NodeSelector: s.Config.Kubernetes.NodeSelector,
Containers: append([]api.Container{
s.buildContainer("build", buildImage, s.buildRequests, s.buildLimits, s.BuildShell.DockerCommand...),
s.buildContainer("helper", s.Config.Kubernetes.GetHelperImage(), s.helperRequests, s.helperLimits, s.BuildShell.DockerCommand...),
......@@ -388,23 +391,55 @@ func (s *executor) overwriteNamespace(job *common.Build) error {
return nil
}
var err error
var r *regexp.Regexp
if r, err = regexp.Compile(s.Config.Kubernetes.NamespaceOverwriteAllowed); err != nil {
if err := overwriteRegexCheck(s.Config.Kubernetes.NamespaceOverwriteAllowed, s.namespaceOverwrite); err != nil {
return err
}
if match := r.MatchString(s.namespaceOverwrite); !match {
return fmt.Errorf("KUBERNETES_NAMESPACE_OVERWRITE='%s' does not match 'namespace_overwrite_allowed': '%s'",
s.namespaceOverwrite, s.Config.Kubernetes.NamespaceOverwriteAllowed)
}
s.Println("Overwritting configured namespace, from", s.Config.Kubernetes.Namespace, "to", s.namespaceOverwrite)
s.Config.Kubernetes.Namespace = s.namespaceOverwrite
return nil
}
// overwriteSercviceAccount checks for variable in order to overwrite the configured
// service account, as long as it complies to validation regular-expression, when
// expression is empty the overwrite is disabled.
func (s *executor) overwriteServiceAccount(job *common.Build) error {
if s.Config.Kubernetes.ServiceAccountOverwriteAllowed == "" {
s.Debugln("Configuration entry 'service_accunt_overwrite_allowed' is empty, disabling override.")
return nil
}
s.serviceAccountOverwrite = job.Variables.Expand().Get("KUBERNETES_SERVICE_ACCOUNT_OVERWRITE")
if s.serviceAccountOverwrite == "" {
return nil
}
if err := overwriteRegexCheck(s.Config.Kubernetes.ServiceAccountOverwriteAllowed, s.serviceAccountOverwrite); err != nil {
return err
}
s.Println("Overwritting configured ServiceAccount, from", s.Config.Kubernetes.ServiceAccount, "to", s.serviceAccountOverwrite)
s.Config.Kubernetes.ServiceAccount = s.serviceAccountOverwrite
return nil
}
//overwriteRegexCheck check if the regex provided for overwriting a config field matches the
//paramether provided, returns error if doesn't match
func overwriteRegexCheck(regex, value string) error {
var err error
var r *regexp.Regexp
if r, err = regexp.Compile(regex); err != nil {
return err
}
if match := r.MatchString(value); !match {
return fmt.Errorf("Provided value %s does not match regex %s", value, regex)
}
return nil
}
func createFn() common.Executor {
return &executor{
AbstractExecutor: executors.AbstractExecutor{
......
......@@ -224,22 +224,165 @@ func TestPrepare(t *testing.T) {
RunnerConfig: &common.RunnerConfig{
RunnerSettings: common.RunnerSettings{
Kubernetes: &common.KubernetesConfig{
Host: "test-server",
Namespace: "namespace",
NamespaceOverwriteAllowed: "^n.*?e$",
ServiceCPULimit: "100m",
ServiceMemoryLimit: "200Mi",
CPULimit: "1.5",
MemoryLimit: "4Gi",
HelperCPULimit: "50m",
HelperMemoryLimit: "100Mi",
ServiceCPURequest: "99m",
ServiceMemoryRequest: "5Mi",
CPURequest: "1",
MemoryRequest: "1.5Gi",
HelperCPURequest: "0.5m",
HelperMemoryRequest: "42Mi",
Privileged: false,
Host: "test-server",
ServiceAccount: "default",
ServiceAccountOverwriteAllowed: ".*",
ServiceCPULimit: "100m",
ServiceMemoryLimit: "200Mi",
CPULimit: "1.5",
MemoryLimit: "4Gi",
HelperCPULimit: "50m",
HelperMemoryLimit: "100Mi",
ServiceCPURequest: "99m",
ServiceMemoryRequest: "5Mi",
CPURequest: "1",
MemoryRequest: "1.5Gi",
HelperCPURequest: "0.5m",
HelperMemoryRequest: "42Mi",
Privileged: false,
},
},
},
Build: &common.Build{
JobResponse: common.JobResponse{
GitInfo: common.GitInfo{
Sha: "1234567890",
},
Image: common.Image{
Name: "test-image",
},
Variables: []common.JobVariable{
{Key: "KUBERNETES_SERVICE_ACCOUNT_OVERWRITE", Value: "not-default"},
},
},
Runner: &common.RunnerConfig{},
},
Expected: &executor{
options: &kubernetesOptions{
Image: "test-image",
},
serviceAccountOverwrite: "not-default",
serviceLimits: api.ResourceList{
api.ResourceCPU: resource.MustParse("100m"),
api.ResourceMemory: resource.MustParse("200Mi"),
},
buildLimits: api.ResourceList{
api.ResourceCPU: resource.MustParse("1.5"),
api.ResourceMemory: resource.MustParse("4Gi"),
},
helperLimits: api.ResourceList{
api.ResourceCPU: resource.MustParse("50m"),
api.ResourceMemory: resource.MustParse("100Mi"),
},
serviceRequests: api.ResourceList{
api.ResourceCPU: resource.MustParse("99m"),
api.ResourceMemory: resource.MustParse("5Mi"),
},
buildRequests: api.ResourceList{
api.ResourceCPU: resource.MustParse("1"),
api.ResourceMemory: resource.MustParse("1.5Gi"),
},
helperRequests: api.ResourceList{
api.ResourceCPU: resource.MustParse("0.5m"),
api.ResourceMemory: resource.MustParse("42Mi"),
},
},
Error: false,
},
{
GlobalConfig: &common.Config{},
RunnerConfig: &common.RunnerConfig{
RunnerSettings: common.RunnerSettings{
Kubernetes: &common.KubernetesConfig{
Host: "test-server",
ServiceAccount: "default",
ServiceAccountOverwriteAllowed: "allowed-.*",
ServiceCPULimit: "100m",
ServiceMemoryLimit: "200Mi",
CPULimit: "1.5",
MemoryLimit: "4Gi",
HelperCPULimit: "50m",
HelperMemoryLimit: "100Mi",
ServiceCPURequest: "99m",
ServiceMemoryRequest: "5Mi",
CPURequest: "1",
MemoryRequest: "1.5Gi",
HelperCPURequest: "0.5m",
HelperMemoryRequest: "42Mi",
Privileged: false,
},
},
},
Build: &common.Build{
JobResponse: common.JobResponse{
GitInfo: common.GitInfo{
Sha: "1234567890",
},
Image: common.Image{
Name: "test-image",
},
Variables: []common.JobVariable{
{Key: "KUBERNETES_SERVICE_ACCOUNT_OVERWRITE", Value: "not-default"},
},
},
Runner: &common.RunnerConfig{},
},
Expected: &executor{
options: &kubernetesOptions{
Image: "test-image",
},
namespaceOverwrite: "namespacee",
serviceLimits: api.ResourceList{
api.ResourceCPU: resource.MustParse("100m"),
api.ResourceMemory: resource.MustParse("200Mi"),
},
buildLimits: api.ResourceList{
api.ResourceCPU: resource.MustParse("1.5"),
api.ResourceMemory: resource.MustParse("4Gi"),
},
helperLimits: api.ResourceList{
api.ResourceCPU: resource.MustParse("50m"),
api.ResourceMemory: resource.MustParse("100Mi"),
},
serviceRequests: api.ResourceList{
api.ResourceCPU: resource.MustParse("99m"),
api.ResourceMemory: resource.MustParse("5Mi"),
},
buildRequests: api.ResourceList{
api.ResourceCPU: resource.MustParse("1"),
api.ResourceMemory: resource.MustParse("1.5Gi"),
},
helperRequests: api.ResourceList{
api.ResourceCPU: resource.MustParse("0.5m"),
api.ResourceMemory: resource.MustParse("42Mi"),
},
},
Error: true,
},
{
GlobalConfig: &common.Config{},
RunnerConfig: &common.RunnerConfig{
RunnerSettings: common.RunnerSettings{
Kubernetes: &common.KubernetesConfig{
Host: "test-server",
Namespace: "namespace",
ServiceAccount: "default",
ServiceAccountOverwriteAllowed: ".*",
NamespaceOverwriteAllowed: "^n.*?e$",
ServiceCPULimit: "100m",
ServiceMemoryLimit: "200Mi",
CPULimit: "1.5",
MemoryLimit: "4Gi",
HelperCPULimit: "50m",
HelperMemoryLimit: "100Mi",
ServiceCPURequest: "99m",
ServiceMemoryRequest: "5Mi",
CPURequest: "1",
MemoryRequest: "1.5Gi",
HelperCPURequest: "0.5m",
HelperMemoryRequest: "42Mi",
Privileged: false,
},
},
},
......@@ -911,6 +1054,40 @@ func TestOverwriteNamespaceNotMatch(t *testing.T) {
assert.Contains(t, err.Error(), "does not match")
}
func TestOverwriteServiceAccountNotMatch(t *testing.T) {
if helpers.SkipIntegrationTests(t, "kubectl", "cluster-info") {
return
}
build := &common.Build{
JobResponse: common.JobResponse{
GitInfo: common.GitInfo{
Sha: "1234567890",
},
Image: common.Image{
Name: "test-image",
},
Variables: []common.JobVariable{
{Key: "KUBERNETES_SERVICE_ACCOUNT_OVERWRITE", Value: "service-account"},
},
},
Runner: &common.RunnerConfig{
RunnerSettings: common.RunnerSettings{
Executor: "kubernetes",
Kubernetes: &common.KubernetesConfig{
ServiceAccountOverwriteAllowed: "^not_a_match$",
},
},
},
SystemInterrupt: make(chan os.Signal, 1),
}
build.Image.Name = "docker:git"
err := build.Run(&common.Config{}, &common.Trace{Writer: os.Stdout})
require.Error(t, err)
assert.Contains(t, err.Error(), "does not match")
}
type FakeReadCloser struct {
io.Reader
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment