Skip to content

Commit

Permalink
Enable Bundles and Custom Tasks when alpha feature gate is set to "al…
Browse files Browse the repository at this point in the history
…pha"

Prior to this commit the Tekton Bundles and Custom Task features were only enabled
when their individual flags were set to "true" in the feature-flags configmap.

After this commit the two features are enabled if enable-api-fields is "alpha" or
if their individual flags are set to "true". Note that it is _not_ possible to
set the "alpha" feature gate but disable Bundles / Custom Tasks. These features
are "alpha features" so they're always enabled regardless of their own feature
flags if the gate is set to "alpha".
  • Loading branch information
Scott authored and tekton-robot committed May 3, 2021
1 parent d7672f9 commit 565c55b
Show file tree
Hide file tree
Showing 11 changed files with 110 additions and 21 deletions.
4 changes: 2 additions & 2 deletions docs/developers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -451,11 +451,11 @@ backwards-compatibility of the examples under alpha conditions.

### Integration Tests

For integration tests we provide the [`requireGate` function](../../test/gate.go) which
For integration tests we provide the [`requireAnyGate` function](../../test/gate.go) which
should be passed to the `setup` function used by tests:

```go
c, namespace := setup(ctx, t, requireGate("enable-api-fields", "alpha"))
c, namespace := setup(ctx, t, requireAnyGate(map[string]string{"enable-api-fields": "alpha"}))
```

This will Skip your integration test if the feature gate is not set to `alpha`
Expand Down
11 changes: 11 additions & 0 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,17 @@ data:
enable-api-fields: "alpha" # Allow alpha fields to be used in Tasks and Pipelines.
```
### Alpha Features
Alpha features are still in development and their syntax is subject to change.
To enable these, set the `enable-api-fields` feature flag to `"alpha"` in
the `feature-flags` ConfigMap alongside your Tekton Pipelines deployment.

Features currently in "alpha" are:

- [Tekton Bundles](./taskruns.md#tekton-bundles)
- [Custom Tasks](./runs.md)

## Configuring High Availability

If you want to run Tekton Pipelines in a way so that webhooks are resiliant against failures and support
Expand Down
3 changes: 2 additions & 1 deletion docs/taskruns.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ spec:
### Tekton Bundles

**Note: This is only allowed if `enable-tekton-oci-bundles` is set to
`"true"` in the `feature-flags` configmap, see [`install.md`](./install.md#customizing-the-pipelines-controller-behavior)**
`"true"` or `enable-api-fields` is set to `"alpha"` in the `feature-flags`
configmap, see [`install.md`](./install.md#customizing-the-pipelines-controller-behavior)**

You may also reference `Tasks` that are defined outside of your cluster using `Tekton
Bundles`. A `Tekton Bundle` is an OCI artifact that contains Tekton resources like `Tasks`
Expand Down
8 changes: 8 additions & 0 deletions examples/v1beta1/taskruns/workspace-in-sidecar.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ spec:
- name: signals
steps:
- image: alpine:3.12.0
resources:
requests:
memory: "64Mi"
cpu: "250m"
script: |
#!/usr/bin/env ash
echo "foo" > "$(workspaces.signals.path)"/bar
Expand All @@ -30,6 +34,10 @@ spec:
echo "Saw ready file"
sidecars:
- image: alpine:3.12.0
resources:
requests:
memory: "64Mi"
cpu: "250m"
# Note: must explicitly add volumeMount to gain access to Workspace in sidecar
volumeMounts:
- name: $(workspaces.signals.volume)
Expand Down
24 changes: 18 additions & 6 deletions pkg/apis/config/feature_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,27 @@ func NewFeatureFlagsFromMap(cfgMap map[string]string) (*FeatureFlags, error) {
if err := setFeature(requireGitSSHSecretKnownHostsKey, DefaultRequireGitSSHSecretKnownHosts, &tc.RequireGitSSHSecretKnownHosts); err != nil {
return nil, err
}
if err := setFeature(enableTektonOCIBundles, DefaultEnableTektonOciBundles, &tc.EnableTektonOCIBundles); err != nil {
return nil, err
}
if err := setFeature(enableCustomTasks, DefaultEnableCustomTasks, &tc.EnableCustomTasks); err != nil {
return nil, err
}
if err := setEnabledAPIFields(cfgMap, DefaultEnableAPIFields, &tc.EnableAPIFields); err != nil {
return nil, err
}

// Given that they are alpha features, Tekton Bundles and Custom Tasks should be switched on if
// enable-api-fields is "alpha". If enable-api-fields is not "alpha" then fall back to the value of
// each feature's individual flag.
//
// Note: the user cannot enable "alpha" while disabling bundles or custom tasks - that would
// defeat the purpose of having a single shared gate for all alpha features.
if tc.EnableAPIFields == AlphaAPIFields {
tc.EnableTektonOCIBundles = true
tc.EnableCustomTasks = true
} else {
if err := setFeature(enableTektonOCIBundles, DefaultEnableTektonOciBundles, &tc.EnableTektonOCIBundles); err != nil {
return nil, err
}
if err := setFeature(enableCustomTasks, DefaultEnableCustomTasks, &tc.EnableCustomTasks); err != nil {
return nil, err
}
}
return &tc, nil
}

Expand Down
22 changes: 22 additions & 0 deletions pkg/apis/config/feature_flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,28 @@ func TestNewFeatureFlagsFromConfigMap(t *testing.T) {
},
fileName: "feature-flags-all-flags-set",
},
{
expectedConfig: &config.FeatureFlags{
EnableAPIFields: "alpha",
// These are prescribed as true by enabling "alpha" API fields, even
// if the submitted text value is "false".
EnableTektonOCIBundles: true,
EnableCustomTasks: true,

RunningInEnvWithInjectedSidecars: config.DefaultRunningInEnvWithInjectedSidecars,
},
fileName: "feature-flags-enable-api-fields-overrides-bundles-and-custom-tasks",
},
{
expectedConfig: &config.FeatureFlags{
EnableAPIFields: "stable",
EnableTektonOCIBundles: true,
EnableCustomTasks: true,

RunningInEnvWithInjectedSidecars: config.DefaultRunningInEnvWithInjectedSidecars,
},
fileName: "feature-flags-bundles-and-custom-tasks",
},
}

for _, tc := range testCases {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: feature-flags
namespace: tekton-pipelines
data:
enable-tekton-oci-bundles: "true"
enable-custom-tasks: "true"
enable-api-fields: "stable"
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: feature-flags
namespace: tekton-pipelines
data:
enable-tekton-oci-bundles: "false"
enable-custom-tasks: "false"
enable-api-fields: "alpha"
7 changes: 6 additions & 1 deletion test/custom_task_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,16 @@ const (
kind = "Example"
)

var supportedFeatureGates = map[string]string{
"enable-custom-tasks": "true",
"enable-api-fields": "alpha",
}

func TestCustomTask(t *testing.T) {
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
c, namespace := setup(ctx, t, requireGate("enable-custom-tasks", "true"))
c, namespace := setup(ctx, t, requireAnyGate(supportedFeatureGates))
knativetest.CleanupOnInterrupt(func() { tearDown(ctx, t, c, namespace) }, t.Logf)
defer tearDown(ctx, t, c, namespace)

Expand Down
23 changes: 15 additions & 8 deletions test/gate.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,33 @@ package test

import (
"context"
"fmt"
"strings"
"testing"

"github.com/tektoncd/pipeline/pkg/apis/config"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"knative.dev/pkg/system"
)

// requireGate returns a setup func that will skip the current
// test if the feature-flag with given name does not equal
// given value. It will fatally fail the test if it cannot get
// the feature-flag configmap.
func requireGate(name, value string) func(context.Context, *testing.T, *clients, string) {
// requireAnyGate returns a setup func that will skip the current
// test if none of the feature-flags in the given map match
// what's in the feature-flags ConfigMap. It will fatally fail
// the test if it cannot get the feature-flag configmap.
func requireAnyGate(gates map[string]string) func(context.Context, *testing.T, *clients, string) {
return func(ctx context.Context, t *testing.T, c *clients, namespace string) {
featureFlagsCM, err := c.KubeClient.CoreV1().ConfigMaps(system.Namespace()).Get(ctx, config.GetFeatureFlagsConfigName(), metav1.GetOptions{})
if err != nil {
t.Fatalf("Failed to get ConfigMap `%s`: %s", config.GetFeatureFlagsConfigName(), err)
}
val, ok := featureFlagsCM.Data[name]
if !ok || val != value {
t.Skipf("Skipped because feature gate %q != %q", name, value)
pairs := []string{}
for name, value := range gates {
actual, ok := featureFlagsCM.Data[name]
if ok && value == actual {
return
}
pairs = append(pairs, fmt.Sprintf("%q: %q", name, value))
}
t.Skipf("No feature flag matching %s", strings.Join(pairs, " or "))
}
}
11 changes: 8 additions & 3 deletions test/tektonbundles_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,16 @@ import (
knativetest "knative.dev/pkg/test"
)

var requireFeatureFlags = requireAnyGate(map[string]string{
"enable-tekton-oci-bundles": "true",
"enable-api-fields": "alpha",
})

// TestTektonBundlesSimpleWorkingExample is an integration test which tests a simple, working Tekton bundle using OCI
// images.
func TestTektonBundlesSimpleWorkingExample(t *testing.T) {
ctx := context.Background()
c, namespace := setup(ctx, t, withRegistry, requireGate("enable-tekton-oci-bundles", "true"))
c, namespace := setup(ctx, t, withRegistry, requireFeatureFlags)

t.Parallel()

Expand Down Expand Up @@ -189,7 +194,7 @@ func TestTektonBundlesSimpleWorkingExample(t *testing.T) {
// TestTektonBundlesUsingRegularImage is an integration test which passes a non-Tekton bundle as a task reference.
func TestTektonBundlesUsingRegularImage(t *testing.T) {
ctx := context.Background()
c, namespace := setup(ctx, t, withRegistry, requireGate("enable-tekton-oci-bundles", "true"))
c, namespace := setup(ctx, t, withRegistry, requireFeatureFlags)

t.Parallel()

Expand Down Expand Up @@ -274,7 +279,7 @@ func TestTektonBundlesUsingRegularImage(t *testing.T) {
// task reference.
func TestTektonBundlesUsingImproperFormat(t *testing.T) {
ctx := context.Background()
c, namespace := setup(ctx, t, withRegistry, requireGate("enable-tekton-oci-bundles", "true"))
c, namespace := setup(ctx, t, withRegistry, requireFeatureFlags)

t.Parallel()

Expand Down

0 comments on commit 565c55b

Please sign in to comment.