Skip to content
Open
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
42 changes: 42 additions & 0 deletions BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,48 @@ generic tests (global `/test` folder) and extension-specific tests (target
task e2e:test TARGET="<extension>" KUBECONFIG_PATH="./kubeconfig"
```

### Testing with Private Registries

When testing extensions hosted in private container registries, you need to
configure both Kubernetes authentication and provide credentials when creating testing values.

#### Step 1: Create a pull secret in your cluster

First, create a Kubernetes pull secret in the namespace where tests will run:

```bash
kubectl create secret docker-registry my-registry-secret \
--docker-server=<registry-url> \
--docker-username=<username> \
--docker-password=<password> \
--namespace=<test-namespace>
```

#### Step 2: Generate test values with registry credentials

Use the `generate-values` task with registry credentials so required image information can
be fetched from the registry and included in the generated values file:

```bash
export REGISTRY_PASSWORD="<your-password>"
task generate-values \
TARGET="<extension>" \
EXTENSION_IMAGE="<private-registry/image:tag>" \
REGISTRY_USERNAME="<username>"
```

#### Step 3: Run tests with namespace and pull secret reference

Pass the namespace and pull secret name to the test execution using extra
Chainsaw arguments:

```bash
task e2e:test \
TARGET="<extension>" \
KUBECONFIG_PATH="./kubeconfig" \
EXTRA_ARGS="--namespace,<test-namespace>,--set,pull_secret=my-registry-secret"
```

---

### Tear down the local test environment
Expand Down
9 changes: 7 additions & 2 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -157,13 +157,17 @@ tasks:
prefix: 'generate-values-{{.TARGET}}'
vars:
EXTENSION_IMAGE: '{{ .EXTENSION_IMAGE| default "" }}'
REGISTRY_USERNAME: '{{ .REGISTRY_USERNAME| default "" }}'
env:
_EXPERIMENTAL_DAGGER_RUNNER_HOST: '{{ ._EXPERIMENTAL_DAGGER_RUNNER_HOST | default "" }}'
REGISTRY_PASSWORD: '{{ .REGISTRY_PASSWORD | default "" }}'
cmds:
- echo -e "{{.BLUE}}Generating values for target {{.TARGET}}...{{.NC}}"
- >
dagger call -sm ./dagger/maintenance/ generate-testing-values
--target {{ .TARGET }} --extension-image="{{ .EXTENSION_IMAGE }}" export --path {{.TARGET}}/values.yaml
--target {{ .TARGET }} --extension-image="{{ .EXTENSION_IMAGE }}"
--registry-username="{{ .REGISTRY_USERNAME }}" --registry-password="env://REGISTRY_PASSWORD"
export --path {{.TARGET}}/values.yaml
requires:
vars:
- name: TARGET
Expand Down Expand Up @@ -347,11 +351,12 @@ tasks:
silent: true
vars:
KUBECONFIG_PATH: '{{ .KUBECONFIG_PATH | default "~/.kube/config" }}'
EXTRA_ARGS: '{{ .EXTRA_ARGS | default "" }}'
env:
_EXPERIMENTAL_DAGGER_RUNNER_HOST: container://{{ .DAGGER_ENGINE_NAME }}
cmds:
- echo -e "{{ .BLUE }}Testing {{ .TARGET }}...{{ .NC }}"
- dagger call -m ./dagger/maintenance/ test --source . --target {{ .TARGET }} --kubeconfig {{ .KUBECONFIG_PATH }}
- dagger call -m ./dagger/maintenance/ test --source . --target {{ .TARGET }} --kubeconfig {{ .KUBECONFIG_PATH }} --extra-args "{{ .EXTRA_ARGS }}"
requires:
vars:
- name: TARGET
Expand Down
23 changes: 21 additions & 2 deletions dagger/maintenance/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ package main

import (
"bytes"
"context"
"fmt"
"regexp"
"strconv"

"dagger/maintenance/internal/dagger"

"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/crane"
"github.com/google/go-containerregistry/pkg/name"
containerregistryv1 "github.com/google/go-containerregistry/pkg/v1"
Expand All @@ -24,14 +28,29 @@ var SupportedDistributions = []string{
}

// getImageAnnotations returns the OCI annotations given an image ref.
func getImageAnnotations(imageRef string) (map[string]string, error) {
// If username and password are provided, they will be used for registry authentication.
func getImageAnnotations(ctx context.Context, imageRef string, username string, password *dagger.Secret) (map[string]string, error) {
// Setting Insecure option to allow fetching images from local registries with no TLS
ref, err := name.ParseReference(imageRef, name.Insecure)
if err != nil {
return nil, err
}

head, err := remote.Get(ref)
var opts []remote.Option
if password != nil {
plainPassword, err := password.Plaintext(ctx)
if err != nil {
return nil, fmt.Errorf("failed to read registry password: %w", err)
}

auth := authn.FromConfig(authn.AuthConfig{
Username: username,
Password: plainPassword,
})
opts = append(opts, remote.WithAuth(auth))
}

head, err := remote.Get(ref, opts...)
if err != nil {
return nil, err
}
Expand Down
32 changes: 28 additions & 4 deletions dagger/maintenance/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,12 @@ func (m *Maintenance) GenerateTestingValues(
// URL reference to the extension image to test [REPOSITORY[:TAG]]
// +optional
extensionImage string,
// Registry username for authentication (optional)
// +optional
registryUsername string,
// Registry password or token for authentication (optional)
// +optional
registryPassword *dagger.Secret,
) (*dagger.File, error) {
metadata, err := parseExtensionMetadata(ctx, target)
if err != nil {
Expand All @@ -161,7 +167,7 @@ func (m *Maintenance) GenerateTestingValues(
}
}

annotations, err := getImageAnnotations(targetExtensionImage)
annotations, err := getImageAnnotations(ctx, targetExtensionImage, registryUsername, registryPassword)
if err != nil {
return nil, err
}
Expand All @@ -180,7 +186,7 @@ func (m *Maintenance) GenerateTestingValues(
targetExtensionImage)
}

extensionInfos, err := generateTestingValuesExtensions(ctx, source, metadata, targetExtensionImage, version)
extensionInfos, err := generateTestingValuesExtensions(ctx, source, metadata, targetExtensionImage, version, registryUsername, registryPassword)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -348,6 +354,9 @@ func (m *Maintenance) Test(
// renovate: datasource=docker depName=kyverno/chainsaw packageName=ghcr.io/kyverno/chainsaw versioning=docker
// +default="ghcr.io/kyverno/chainsaw:v0.2.14@sha256:c703e4d4ce7b89c5121fe957ab89b6e2d33f91fd15f8274a9f79ca1b2ba8ecef"
chainsawImage string,
// Additional arguments to pass to Chainsaw test command
// +optional
extraArgs []string,
) error {
extDir := source
if target != "all" {
Expand Down Expand Up @@ -392,8 +401,15 @@ func (m *Maintenance) Test(
WithFile("/etc/kubeconfig/config", kubeconfig).
WithEnvVariable("KUBECONFIG", "/etc/kubeconfig/config")

chainsawTestArgs := []string{
"test",
"./test",
"--values", path.Join(extName, valuesFile),
}
chainsawTestArgs = append(chainsawTestArgs, extraArgs...)

_, err = ctr.WithExec(
[]string{"test", "./test", "--values", path.Join(extName, valuesFile)},
chainsawTestArgs,
dagger.ContainerWithExecOpts{
UseEntrypoint: true,
}).
Expand All @@ -410,8 +426,16 @@ func (m *Maintenance) Test(
if !hasIndividualTests {
continue
}

chainsawTestArgs = []string{
"test",
path.Join(extName, "test"),
"--values", path.Join(extName, valuesFile),
}
chainsawTestArgs = append(chainsawTestArgs, extraArgs...)

_, err = ctr.WithExec(
[]string{"test", path.Join(extName, "test"), "--values", path.Join(extName, valuesFile)},
chainsawTestArgs,
dagger.ContainerWithExecOpts{
UseEntrypoint: true,
}).
Expand Down
5 changes: 3 additions & 2 deletions dagger/maintenance/testingvalues.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ type testingExtensionInfo struct {
CreateExtension bool
}

func generateTestingValuesExtensions(ctx context.Context, source *dagger.Directory, metadata *extensionMetadata, extensionImage string, version string) ([]*testingExtensionInfo, error) {
func generateTestingValuesExtensions(ctx context.Context, source *dagger.Directory, metadata *extensionMetadata,
extensionImage string, version string, registryUsername string, registryPassword *dagger.Secret) ([]*testingExtensionInfo, error) {
var out []*testingExtensionInfo
configuration, err := generateExtensionConfiguration(metadata, extensionImage)
if err != nil {
Expand Down Expand Up @@ -67,7 +68,7 @@ func generateTestingValuesExtensions(ctx context.Context, source *dagger.Directo
return nil, err
}

depAnnotations, err := getImageAnnotations(depConfiguration.ImageVolumeSource.Reference)
depAnnotations, err := getImageAnnotations(ctx, depConfiguration.ImageVolumeSource.Reference, registryUsername, registryPassword)
if err != nil {
return nil, err
}
Expand Down
3 changes: 3 additions & 0 deletions postgis/test/cluster.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ spec:
imageName: ($values.pg_image)
instances: 1

imagePullSecrets:
- name: ($values.pull_secret)

storage:
size: 1Gi

Expand Down
3 changes: 3 additions & 0 deletions test/cluster.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ spec:
storage:
size: 1Gi

imagePullSecrets:
- name: ($values.pull_secret)

postgresql:
shared_preload_libraries: ($values.shared_preload_libraries)
extensions: ($values.extensions)