Skip to content

Commit

Permalink
added support for default pod template
Browse files Browse the repository at this point in the history
fix task test
  • Loading branch information
charles-edouard.breteche authored and tekton-robot committed Jan 20, 2020
1 parent b859371 commit eb26f85
Show file tree
Hide file tree
Showing 27 changed files with 900 additions and 199 deletions.
5 changes: 5 additions & 0 deletions config/config-defaults.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,8 @@ data:
# TaskRuns. If a user's requested TaskRun specifies another value for this
# label, the user's request supercedes.
default-managed-by-label-value: "tekton-pipelines"
# default-pod-template contains the default pod template to use
# TaskRun and PipelineRun, if none is specified. If a pod template
# is specified, the default pod template is ignored.
# default-pod-template:
28 changes: 18 additions & 10 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ stringData:
https_validate_certificates = True
---
apiVersion: v1
data: null
kind: ConfigMap
metadata:
name: config-artifact-pvc
Expand All @@ -181,24 +180,33 @@ creation of a persistent volume could be slower than uploading/downloading files
to a bucket, or if the the cluster is running in multiple zones, the access to
the persistent volume can fail.
### Overriding default ServiceAccount used for TaskRun and PipelineRun
### Overriding default ServiceAccount, Timeout or PodTemplate used for TaskRun and PipelineRun
The ConfigMap `config-defaults` can be used to override default service account
e.g. to override the default service account (`default`) to `tekton` apply the
following
The ConfigMap `config-defaults` can be used to override default values.
You can override the default service account, the default timeout, and the
default pod template applied to `TaskRun` and `PipelineRun`.
```yaml
The example below overrides the following :
- the default service account (`default`) to `tekton`
- the default timeout (60 minutes) to 20 minutes
- the default pod template to include an annotation preventing clusterautoscaler to evict a running task pod
(see [here](./taskruns.md#pod-template) or [here](./pipelineruns.md#pod-template) for more infos on pod templates)
### config-defaults.yaml
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: config-defaults
data:
default-service-account: "tekton"
default-timeout-minutes: "20"
default-pod-template: |
annotations:
cluster-autoscaler.kubernetes.io/safe-to-evict: 'false'
```
*NOTE:* The `_example` key contains of the keys that can be overriden and their
default values.
*NOTE:* The `_example` key in the provided [config-defaults.yaml](./../config/config-defaults.yaml)
file contains the keys that can be overriden and their default values.
## Custom Releases
Expand Down
4 changes: 4 additions & 0 deletions docs/podtemplates.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ configuration that will be used as the basis for the `Task` pod.

This allows to customize some Pod specific field per `Task` execution, aka `TaskRun`.

Alternatively, you can also define a default pod template in tekton config, see [here](./install.md)
When a pod template is specified for a `PipelineRun` or `TaskRun`, the default pod template is ignored, ie
both templates are **NOT** merged, it's always one or the other.

---

The current fields supported are:
Expand Down
5 changes: 5 additions & 0 deletions hack/update-codegen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ ${GOPATH}/bin/deepcopy-gen \
--go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt \
-i github.com/tektoncd/pipeline/pkg/apis/config

${GOPATH}/bin/deepcopy-gen \
-O zz_generated.deepcopy \
--go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt \
-i github.com/tektoncd/pipeline/pkg/apis/pipeline/pod

# Knative Injection
# This generates the knative injection packages for the resource package (v1alpha1).
# This is separate from the pipeline package for the same reason as client and all (see above).
Expand Down
25 changes: 24 additions & 1 deletion pkg/apis/config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"strconv"
"time"

"github.com/ghodss/yaml"
"github.com/tektoncd/pipeline/pkg/apis/pipeline/pod"
corev1 "k8s.io/api/core/v1"
)

Expand All @@ -33,6 +35,7 @@ const (
defaultServiceAccountKey = "default-service-account"
defaultManagedByLabelValueKey = "default-managed-by-label-value"
DefaultManagedByLabelValue = "tekton-pipelines"
defaultPodTemplateKey = "default-pod-template"
)

// Defaults holds the default configurations
Expand All @@ -41,13 +44,23 @@ type Defaults struct {
DefaultTimeoutMinutes int
DefaultServiceAccount string
DefaultManagedByLabelValue string
DefaultPodTemplate *pod.Template
}

// Equals returns true if two Configs are identical
func (cfg *Defaults) Equals(other *Defaults) bool {
if cfg == nil && other == nil {
return true
}

if cfg == nil || other == nil {
return false
}

return other.DefaultTimeoutMinutes == cfg.DefaultTimeoutMinutes &&
other.DefaultServiceAccount == cfg.DefaultServiceAccount &&
other.DefaultManagedByLabelValue == cfg.DefaultManagedByLabelValue
other.DefaultManagedByLabelValue == cfg.DefaultManagedByLabelValue &&
other.DefaultPodTemplate.Equals(cfg.DefaultPodTemplate)
}

// NewDefaultsFromMap returns a Config given a map corresponding to a ConfigMap
Expand All @@ -56,6 +69,7 @@ func NewDefaultsFromMap(cfgMap map[string]string) (*Defaults, error) {
DefaultTimeoutMinutes: DefaultTimeoutMinutes,
DefaultManagedByLabelValue: DefaultManagedByLabelValue,
}

if defaultTimeoutMin, ok := cfgMap[defaultTimeoutMinutesKey]; ok {
timeout, err := strconv.ParseInt(defaultTimeoutMin, 10, 0)
if err != nil {
Expand All @@ -67,10 +81,19 @@ func NewDefaultsFromMap(cfgMap map[string]string) (*Defaults, error) {
if defaultServiceAccount, ok := cfgMap[defaultServiceAccountKey]; ok {
tc.DefaultServiceAccount = defaultServiceAccount
}

if defaultManagedByLabelValue, ok := cfgMap[defaultManagedByLabelValueKey]; ok {
tc.DefaultManagedByLabelValue = defaultManagedByLabelValue
}

if defaultPodTemplate, ok := cfgMap[defaultPodTemplateKey]; ok {
var podTemplate pod.Template
if err := yaml.Unmarshal([]byte(defaultPodTemplate), &podTemplate); err != nil {
return nil, fmt.Errorf("failed to unmarshal %v", defaultPodTemplate)
}
tc.DefaultPodTemplate = &podTemplate
}

return &tc, nil
}

Expand Down
158 changes: 153 additions & 5 deletions pkg/apis/config/default_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,58 @@ import (
"testing"

"github.com/google/go-cmp/cmp"
"github.com/tektoncd/pipeline/pkg/apis/pipeline/pod"
test "github.com/tektoncd/pipeline/pkg/reconciler/testing"
)

func TestNewDefaultsFromConfigMap(t *testing.T) {
expectedConfig := &Defaults{
DefaultTimeoutMinutes: 50,
DefaultServiceAccount: "tekton",
DefaultManagedByLabelValue: "something-else",
type testCase struct {
expectedConfig *Defaults
expectedError bool
fileName string
}

testCases := []testCase{
{
expectedConfig: &Defaults{
DefaultTimeoutMinutes: 50,
DefaultServiceAccount: "tekton",
DefaultManagedByLabelValue: "something-else",
},
fileName: DefaultsConfigName,
},
{
expectedConfig: &Defaults{
DefaultTimeoutMinutes: 50,
DefaultServiceAccount: "tekton",
DefaultManagedByLabelValue: DefaultManagedByLabelValue,
DefaultPodTemplate: &pod.Template{
NodeSelector: map[string]string{
"label": "value",
},
},
},
fileName: "config-defaults-with-pod-template",
},
// the github.com/ghodss/yaml package in the vendor directory does not support UnmarshalStrict
// update it, switch to UnmarshalStrict in defaults.go, then uncomment these tests
// {
// expectedError: true,
// fileName: "config-defaults-timeout-err",
// },
// {
// expectedError: true,
// fileName: "config-defaults-pod-template-err",
// },
}

for _, tc := range testCases {
if tc.expectedError {
verifyConfigFileWithExpectedError(t, tc.fileName)
} else {
verifyConfigFileWithExpectedConfig(t, tc.fileName, tc.expectedConfig)
}
}
verifyConfigFileWithExpectedConfig(t, DefaultsConfigName, expectedConfig)
}

func TestNewDefaultsFromEmptyConfigMap(t *testing.T) {
Expand All @@ -41,6 +83,105 @@ func TestNewDefaultsFromEmptyConfigMap(t *testing.T) {
verifyConfigFileWithExpectedConfig(t, DefaultsConfigEmptyName, expectedConfig)
}

func TestEquals(t *testing.T) {
testCases := []struct {
name string
left *Defaults
right *Defaults
expected bool
}{
{
name: "left and right nil",
left: nil,
right: nil,
expected: true,
},
{
name: "left nil",
left: nil,
right: &Defaults{},
expected: false,
},
{
name: "right nil",
left: &Defaults{},
right: nil,
expected: false,
},
{
name: "right and right default",
left: &Defaults{},
right: &Defaults{},
expected: true,
},
{
name: "different default timeout",
left: &Defaults{
DefaultTimeoutMinutes: 10,
},
right: &Defaults{
DefaultTimeoutMinutes: 20,
},
expected: false,
},
{
name: "same default timeout",
left: &Defaults{
DefaultTimeoutMinutes: 20,
},
right: &Defaults{
DefaultTimeoutMinutes: 20,
},
expected: true,
},
{
name: "different default pod template",
left: &Defaults{
DefaultPodTemplate: &pod.Template{
NodeSelector: map[string]string{
"label": "value",
},
},
},
right: &Defaults{
DefaultPodTemplate: &pod.Template{
NodeSelector: map[string]string{
"label2": "value",
},
},
},
expected: false,
},
{
name: "same default pod template",
left: &Defaults{
DefaultPodTemplate: &pod.Template{
NodeSelector: map[string]string{
"label": "value",
},
},
},
right: &Defaults{
DefaultPodTemplate: &pod.Template{
NodeSelector: map[string]string{
"label": "value",
},
},
},
expected: true,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
actual := tc.left.Equals(tc.right)
if actual != tc.expected {
t.Errorf("Comparison failed expected: %t, actual: %t", tc.expected, actual)
}
})
}
}

func verifyConfigFileWithExpectedConfig(t *testing.T, fileName string, expectedConfig *Defaults) {
cm := test.ConfigMapFromTestFile(t, fileName)
if Defaults, err := NewDefaultsFromConfigMap(cm); err == nil {
Expand All @@ -51,3 +192,10 @@ func verifyConfigFileWithExpectedConfig(t *testing.T, fileName string, expectedC
t.Errorf("NewDefaultsFromConfigMap(actual) = %v", err)
}
}

func verifyConfigFileWithExpectedError(t *testing.T, fileName string) {
cm := test.ConfigMapFromTestFile(t, fileName)
if _, err := NewDefaultsFromConfigMap(cm); err == nil {
t.Errorf("NewDefaultsFromConfigMap(actual) was expected to return an error")
}
}
24 changes: 24 additions & 0 deletions pkg/apis/config/testdata/config-defaults-pod-template-err.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright 2019 The Tekton Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: v1
kind: ConfigMap
metadata:
name: config-defaults
namespace: tekton-pipelines
data:
default-timeout-minutes: "50"
default-service-account: "tekton"
default-pod-template: |
badKey: 42
22 changes: 22 additions & 0 deletions pkg/apis/config/testdata/config-defaults-timeout-err.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2019 The Tekton Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: v1
kind: ConfigMap
metadata:
name: config-defaults
namespace: tekton-pipelines
data:
default-timeout-minutes: "abc"
default-service-account: "tekton"
Loading

0 comments on commit eb26f85

Please sign in to comment.