registry

package module
v0.30.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 8, 2024 License: MIT Imports: 13 Imported by: 0

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func WithData

func WithData(dataPath string) testcontainers.CustomizeRequestOption

WithData is a custom option to set the data directory for the registry, which is used to store the images. It will copy the data from the host to the container in the /data path. The container will be configured to use this path as the root directory for the registry, thanks to the REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY environment variable. The dataPath must have the same structure as the registry data directory.

func WithHtpasswd

func WithHtpasswd(credentials string) testcontainers.CustomizeRequestOption

WithHtpasswd is a custom option to set the htpasswd credentials for the registry It will create a temporary file with the credentials and copy it to the container in the /auth/htpasswd path. The container will be configured to use this file as the htpasswd file, thanks to the REGISTRY_AUTH_HTPASSWD_PATH environment variable.

func WithHtpasswdFile

func WithHtpasswdFile(htpasswdPath string) testcontainers.CustomizeRequestOption

WithHtpasswdFile is a custom option to set the htpasswd file for the registry It will copy a file with the credentials in the /auth/htpasswd path. The container will be configured to use this file as the htpasswd file, thanks to the REGISTRY_AUTH_HTPASSWD_PATH environment variable.

Types

type RegistryContainer

type RegistryContainer struct {
	testcontainers.Container
	RegistryName string
}

RegistryContainer represents the Registry container type used in the module

func RunContainer

func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*RegistryContainer, error)

RunContainer creates an instance of the Registry container type

Example
// runRegistryContainer {
registryContainer, err := registry.RunContainer(context.Background(), testcontainers.WithImage("registry:2.8.3"))
if err != nil {
	log.Fatalf("failed to start container: %s", err)
}

// Clean up the container
defer func() {
	if err := registryContainer.Terminate(context.Background()); err != nil {
		log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic
	}
}()
// }

state, err := registryContainer.State(context.Background())
if err != nil {
	log.Fatalf("failed to get container state: %s", err) // nolint:gocritic
}

fmt.Println(state.Running)
Output:

true
Example (PushImage)
registryContainer, err := registry.RunContainer(
	context.Background(),
	testcontainers.WithImage("registry:2.8.3"),
	registry.WithHtpasswdFile(filepath.Join("testdata", "auth", "htpasswd")),
	registry.WithData(filepath.Join("testdata", "data")),
)
if err != nil {
	log.Fatalf("failed to start container: %s", err)
}
defer func() {
	if err := registryContainer.Terminate(context.Background()); err != nil {
		log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic
	}
}()

registryPort, err := registryContainer.MappedPort(context.Background(), "5000/tcp")
if err != nil {
	log.Fatalf("failed to get mapped port: %s", err) // nolint:gocritic
}
strPort := registryPort.Port()

previousAuthConfig := os.Getenv("DOCKER_AUTH_CONFIG")

// make sure the Docker Auth credentials are set
// using the same as in the Docker Registry
// testuser:testpassword
// Besides, we are also setting the authentication
// for both the registry and localhost to make sure
// the image is pushed to the private registry.
os.Setenv("DOCKER_AUTH_CONFIG", `{
		"auths": {
			"localhost:`+strPort+`": { "username": "testuser", "password": "testpassword", "auth": "dGVzdHVzZXI6dGVzdHBhc3N3b3Jk" },
			"`+registryContainer.RegistryName+`": { "username": "testuser", "password": "testpassword", "auth": "dGVzdHVzZXI6dGVzdHBhc3N3b3Jk" }
		},
		"credsStore": "desktop"
	}`)
defer func() {
	// reset the original state after the example.
	os.Unsetenv("DOCKER_AUTH_CONFIG")
	os.Setenv("DOCKER_AUTH_CONFIG", previousAuthConfig)
}()

// build a custom redis image from the private registry,
// using RegistryName of the container as the registry.
// We are agoing to build the image with a fixed tag
// that matches the private registry, and we are going to
// push it again to the registry after the build.

repo := registryContainer.RegistryName + "/customredis"
tag := "v1.2.3"

redisC, err := testcontainers.GenericContainer(context.Background(), testcontainers.GenericContainerRequest{
	ContainerRequest: testcontainers.ContainerRequest{
		FromDockerfile: testcontainers.FromDockerfile{
			Context: filepath.Join("testdata", "redis"),
			BuildArgs: map[string]*string{
				"REGISTRY_PORT": &strPort,
			},
			Repo:          repo,
			Tag:           tag,
			PrintBuildLog: true,
		},
		AlwaysPullImage: true, // make sure the authentication takes place
		ExposedPorts:    []string{"6379/tcp"},
		WaitingFor:      wait.ForLog("Ready to accept connections"),
	},
	Started: true,
})
if err != nil {
	log.Fatalf("failed to start container: %s", err) // nolint:gocritic
}
defer func() {
	if err := redisC.Terminate(context.Background()); err != nil {
		log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic
	}
}()

// pushingImage {
// repo is localhost:32878/customredis
// tag is v1.2.3
err = registryContainer.PushImage(context.Background(), fmt.Sprintf("%s:%s", repo, tag))
if err != nil {
	log.Fatalf("failed to push image: %s", err) // nolint:gocritic
}
// }

newImage := fmt.Sprintf("%s:%s", repo, tag)

// now run a container from the new image
// But first remove the local image to avoid using the local one.

// deletingImage {
// newImage is customredis:v1.2.3
err = registryContainer.DeleteImage(context.Background(), newImage)
if err != nil {
	log.Fatalf("failed to delete image: %s", err) // nolint:gocritic
}
// }

newRedisC, err := testcontainers.GenericContainer(context.Background(), testcontainers.GenericContainerRequest{
	ContainerRequest: testcontainers.ContainerRequest{
		Image:        newImage,
		ExposedPorts: []string{"6379/tcp"},
		WaitingFor:   wait.ForLog("Ready to accept connections"),
	},
	Started: true,
})
if err != nil {
	log.Fatalf("failed to start container from %s: %s", newImage, err) // nolint:gocritic
}
defer func() {
	if err := newRedisC.Terminate(context.Background()); err != nil {
		log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic
	}
}()

state, err := newRedisC.State(context.Background())
if err != nil {
	log.Fatalf("failed to get redis container state from %s: %s", newImage, err) // nolint:gocritic
}

fmt.Println(state.Running)
Output:

true
Example (WithAuthentication)
// htpasswdFile {
registryContainer, err := registry.RunContainer(
	context.Background(),
	testcontainers.WithImage("registry:2.8.3"),
	registry.WithHtpasswdFile(filepath.Join("testdata", "auth", "htpasswd")),
	registry.WithData(filepath.Join("testdata", "data")),
)
// }
if err != nil {
	log.Fatalf("failed to start container: %s", err)
}
defer func() {
	if err := registryContainer.Terminate(context.Background()); err != nil {
		log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic
	}
}()

registryPort, err := registryContainer.MappedPort(context.Background(), "5000/tcp")
if err != nil {
	log.Fatalf("failed to get mapped port: %s", err) // nolint:gocritic
}
strPort := registryPort.Port()

previousAuthConfig := os.Getenv("DOCKER_AUTH_CONFIG")

// make sure the Docker Auth credentials are set
// using the same as in the Docker Registry
// testuser:testpassword
os.Setenv("DOCKER_AUTH_CONFIG", `{
		"auths": {
			"localhost:`+strPort+`": { "username": "testuser", "password": "testpassword", "auth": "dGVzdHVzZXI6dGVzdHBhc3N3b3Jk" }
		},
		"credsStore": "desktop"
	}`)
defer func() {
	// reset the original state after the example.
	os.Unsetenv("DOCKER_AUTH_CONFIG")
	os.Setenv("DOCKER_AUTH_CONFIG", previousAuthConfig)
}()

// build a custom redis image from the private registry,
// using RegistryName of the container as the registry.

redisC, err := testcontainers.GenericContainer(context.Background(), testcontainers.GenericContainerRequest{
	ContainerRequest: testcontainers.ContainerRequest{
		FromDockerfile: testcontainers.FromDockerfile{
			Context: filepath.Join("testdata", "redis"),
			BuildArgs: map[string]*string{
				"REGISTRY_PORT": &strPort,
			},
			PrintBuildLog: true,
		},
		AlwaysPullImage: true, // make sure the authentication takes place
		ExposedPorts:    []string{"6379/tcp"},
		WaitingFor:      wait.ForLog("Ready to accept connections"),
	},
	Started: true,
})
if err != nil {
	log.Fatalf("failed to start container: %s", err) // nolint:gocritic
}
defer func() {
	if err := redisC.Terminate(context.Background()); err != nil {
		log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic
	}
}()

state, err := redisC.State(context.Background())
if err != nil {
	log.Fatalf("failed to get redis container state: %s", err) // nolint:gocritic
}

fmt.Println(state.Running)
Output:

true

func (*RegistryContainer) Address

func (c *RegistryContainer) Address(ctx context.Context) (string, error)

Address returns the address of the Registry container, using the HTTP protocol

func (*RegistryContainer) DeleteImage

func (c *RegistryContainer) DeleteImage(ctx context.Context, imageRef string) error

DeleteImage deletes an image reference from the Registry container. It will use the HTTP endpoint of the Registry container to delete it, doing a HEAD request to get the image digest and then a DELETE request to actually delete the image. E.g. imageRef = "localhost:5000/alpine:latest"

func (*RegistryContainer) ImageExists

func (c *RegistryContainer) ImageExists(ctx context.Context, imageRef string) error

ImageExists checks if an image exists in the Registry container. It will use the v2 HTTP endpoint of the Registry container to check if the image reference exists. E.g. imageRef = "localhost:5000/alpine:latest"

func (*RegistryContainer) PushImage

func (c *RegistryContainer) PushImage(ctx context.Context, ref string) error

PushImage pushes an image to the Registry container. It will use the internally stored RegistryName to push the image to the container, and it will finally wait for the image to be pushed.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL