Skip to content
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
35 changes: 35 additions & 0 deletions BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,20 @@ task e2e:setup-env
> If changed, you must pass this variable to all subsequent tasks that interact
> with the registry to ensure connectivity.

#### Configuring credentials for private registries

If you need to pull images from a private registry during testing, you can
configure authentication credentials when setting up the environment:

```bash
REGISTRY_PASSWORD="your-password" task e2e:setup-env \
REGISTRY_HOST="registry.example.com" \
REGISTRY_USERNAME="your-username"
```

These credentials are configured at the kubelet level, allowing pods to pull
images from the private registry without requiring ImagePullSecrets.

### Get access to the cluster

To interact with the cluster via `kubectl` from your local terminal:
Expand Down Expand Up @@ -218,6 +232,18 @@ the E2E tests:
task e2e:generate-values TARGET="<extension>" EXTENSION_IMAGE="<my-local-image>"
```

#### Using private registries

If your extension image is hosted in a private registry, you can provide authentication
credentials when generating test values:

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

### Execute End-to-End tests

Run the test suite using the internal Kubeconfig. This executes both the
Expand All @@ -228,6 +254,15 @@ generic tests (global `/test` folder) and extension-specific tests (target
task e2e:test TARGET="<extension>" KUBECONFIG_PATH="./kubeconfig"
```

#### Pass arguments to chainsaw test

It is possible to pass arguments to the [Chainsaw test command](https://kyverno.github.io/chainsaw/latest/reference/commands/chainsaw_test/) by using the `EXTRA_ARGS`
argument, like:

```bash
task e2e:test TARGET="pgvector" KUBECONFIG_PATH="./kubeconfig" EXTRA_ARGS="--skip-delete,--fail-fast"
```

---

### Tear down the local test environment
Expand Down
48 changes: 44 additions & 4 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 @@ -218,6 +222,8 @@ tasks:
run: once
vars:
REGISTRY_DIR: /etc/containerd/certs.d/{{ .REGISTRY_NAME }}:{{ .REGISTRY_INTERNAL_PORT }}
REGISTRY_HOST: '{{ .REGISTRY_HOST | default "" }}'
REGISTRY_USERNAME: '{{ .REGISTRY_USERNAME | default "" }}'
DOCKER_SOCKET:
sh: docker context inspect -f {{`'{{json .Endpoints.docker.Host}}'`}} $(docker context show)
env:
Expand All @@ -233,6 +239,20 @@ tasks:
cat <<EOF | docker exec -i "{{ .KIND_CLUSTER_NAME }}-control-plane" cp /dev/stdin "{{ .REGISTRY_DIR }}/hosts.toml"
[host."http://{{ .REGISTRY_NAME }}:{{ .REGISTRY_INTERNAL_PORT }}"]
EOF
- |
if [ -n "{{ .REGISTRY_HOST }}" ] && [ -n "{{ .REGISTRY_USERNAME }}" ] && [ -n "${REGISTRY_PASSWORD}" ]; then
AUTH=$(echo -n "{{ .REGISTRY_USERNAME }}:${REGISTRY_PASSWORD}" | base64 -w0)
docker exec "{{ .KIND_CLUSTER_NAME }}-control-plane" mkdir -p /var/lib/kubelet
cat <<EOF | docker exec -i "{{ .KIND_CLUSTER_NAME }}-control-plane" cp /dev/stdin /var/lib/kubelet/config.json
{
"auths": {
"{{ .REGISTRY_HOST }}": {
"auth": "${AUTH}"
}
}
}
EOF
fi
status:
- >
test "$(dagger call -m github.com/aweris/daggerverse/kind@{{ .DAGGER_KIND_SHA }}
Expand All @@ -241,7 +261,10 @@ tasks:
e2e:install-cnpg:
desc: Install CloudNativePG operator in the Kind cluster
deps:
- e2e:setup-kind
- task: e2e:setup-kind
vars:
REGISTRY_HOST: '{{ .REGISTRY_HOST }}'
REGISTRY_USERNAME: '{{ .REGISTRY_USERNAME }}'
internal: true
vars:
# renovate: datasource=github-tags depName=cloudnative-pg/cloudnative-pg versioning=semver extractVersion=^v(?<version>\d+\.\d+)\.\d+$
Expand Down Expand Up @@ -310,10 +333,16 @@ tasks:
e2e:setup-env:
desc: Setup E2E environment
silent: true
vars:
REGISTRY_HOST: '{{ .REGISTRY_HOST | default "" }}'
REGISTRY_USERNAME: '{{ .REGISTRY_USERNAME | default "" }}'
deps:
- e2e:start-container-registry
- e2e:start-dagger-engine
- e2e:install-cnpg
- task: e2e:install-cnpg
vars:
REGISTRY_HOST: '{{ .REGISTRY_HOST }}'
REGISTRY_USERNAME: '{{ .REGISTRY_USERNAME }}'
cmds:
- echo -e "{{.GREEN}}--- E2E environment setup complete ---{{.NC}}"

Expand All @@ -326,11 +355,15 @@ tasks:
silent: true
vars:
EXTENSION_IMAGE: '{{ .EXTENSION_IMAGE| default "" }}'
REGISTRY_USERNAME: '{{ .REGISTRY_USERNAME| default "" }}'
env:
REGISTRY_PASSWORD: '{{ .REGISTRY_PASSWORD | default "" }}'
cmds:
- task: generate-values
vars:
_EXPERIMENTAL_DAGGER_RUNNER_HOST: container://{{ .DAGGER_ENGINE_NAME }}
TARGET: '{{ .TARGET }}'
REGISTRY_USERNAME: '{{ .REGISTRY_USERNAME }}'
EXTENSION_IMAGE:
# Rewrite host:port to the internal registry name and port used
# within the Docker network.
Expand All @@ -347,11 +380,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 All @@ -374,8 +408,13 @@ tasks:
METADATA_FILE: "{{ .TARGET }}/bake-metadata.json"
KUBECONFIG_PATH: "./kubeconfig"
DISTRO: '{{ .DISTRO | default "trixie" }}'
REGISTRY_HOST: '{{ .REGISTRY_HOST | default "" }}'
REGISTRY_USERNAME: '{{ .REGISTRY_USERNAME | default "" }}'
cmds:
- task: e2e:setup-env
vars:
REGISTRY_HOST: '{{ .REGISTRY_HOST }}'
REGISTRY_USERNAME: '{{ .REGISTRY_USERNAME }}'
- task: bake
vars:
PUSH: "true"
Expand All @@ -385,6 +424,7 @@ tasks:
- task: e2e:generate-values
vars:
TARGET: "{{ .TARGET }}"
REGISTRY_USERNAME: '{{ .REGISTRY_USERNAME }}'
EXTENSION_IMAGE:
sh: >
jq -r --arg distro "{{ .DISTRO }}"
Expand Down
25 changes: 23 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,31 @@ 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 && username != "" {
plainPassword, err := password.Plaintext(ctx)
if err != nil {
return nil, fmt.Errorf("failed to read registry password: %w", err)
}

if plainPassword != "" {
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