Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Bundles and Custom Tasks when feature gate is set to "alpha" #3908

Merged
merged 1 commit into from May 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,
afrittoli marked this conversation as resolved.
Show resolved Hide resolved

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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

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