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

First implementation of DockerRegitry module #1165

Closed
Closed
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
6 changes: 6 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@ updates:
interval: monthly
open-pull-requests-limit: 3
rebase-strategy: disabled
- package-ecosystem: gomod
Copy link
Member

Choose a reason for hiding this comment

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

directory: /modules/dockerregistry
schedule:
interval: monthly
open-pull-requests-limit: 3
rebase-strategy: disabled
- package-ecosystem: gomod
directory: /modules/vault
schedule:
Expand Down
56 changes: 56 additions & 0 deletions .github/workflows/module-dockerregistry.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: DockerRegistry module pipeline
Copy link
Member

Choose a reason for hiding this comment

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

Please take a look at #1414: this module file has been removed in favour of an array of modules in the ci.yml workflow.


on:
push:
paths-ignore:
- 'mkdocs.yml'
- 'docs/**'
- 'README.md'
pull_request:
paths-ignore:
- 'mkdocs.yml'
- 'docs/**'
- 'README.md'

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.sha }}
cancel-in-progress: true

jobs:
test-dockerregistry:
strategy:
matrix:
go-version: [1.19.x, 1.x]
runs-on: "ubuntu-latest"
steps:

- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go-version }}
id: go

- name: Check out code into the Go module directory
uses: actions/checkout@v3

- name: modVerify
working-directory: ./modules/dockerregistry
run: go mod verify

- name: modTidy
working-directory: ./modules/dockerregistry
run: make tools-tidy

- name: gotestsum
working-directory: ./modules/dockerregistry
run: make test-unit

- name: Run checker
run: |
./scripts/check_environment.sh

- name: Test Summary
uses: test-summary/action@4ee9ece4bca777a38f05c8fc578ac2007fe266f7
with:
paths: "**/TEST-dockerregistry*.xml"
if: always()
69 changes: 69 additions & 0 deletions docs/modules/dockerregistry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# DockerRegistry

Not available until the next release of testcontainers-go <a href="https://github.com/testcontainers/testcontainers-go"><span class="tc-version">:material-tag: main</span></a>

## Introduction

The Testcontainers module for Docker Registry.

## Adding this module to your project dependencies

Please run the following command to add the Docker Registry module to your Go dependencies:

```
go get github.com/testcontainers/testcontainers-go/modules/dockerregistry
```

## Usage example

<!--codeinclude-->
[Creating a Docker Registry container](../../modules/dockerregistry/dockerregistry.go)
<!--/codeinclude-->

<!--codeinclude-->
[Test for a Docker Registry container](../../modules/dockerregistry/dockerregistry_test.go)
<!--/codeinclude-->

## Module reference

The Docker Registry module exposes one entrypoint function to create the Docker Registry container, and this function receives two parameters:

```golang
func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*DockerRegistryContainer, error)
```

- `context.Context`, the Go context.
- `testcontainers.ContainerCustomizer`, a variadic argument for passing options.

### Container Options

When starting the Docker Registry container, you can pass options in a variadic way to configure it.

#### Image

If you need to set a different Docker Registry image, you can use `testcontainers.WithImage` with a valid Docker image
for DockerRegistry. E.g. `testcontainers.WithImage("docker.io/registry:latest")`.

#### Wait Strategies

If you need to set a different wait strategy for Docker Registry, you can use `testcontainers.WithWaitStrategy` with a valid wait strategy
for DockerRegistry.

!!!info
The default deadline for the wait strategy is 60 seconds.

At the same time, it's possible to set a wait strategy and a custom deadline with `testcontainers.WithWaitStrategyAndDeadline`.

#### Docker type modifiers

If you need an advanced configuration for Docker Registry, you can leverage the following Docker type modifiers:

- `testcontainers.WithConfigModifier`
- `testcontainers.WithHostConfigModifier`
- `testcontainers.WithEndpointSettingsModifier`

Please read the [Create containers: Advanced Settings](../features/creating_container.md#advanced-settings) documentation for more information.

### Container Methods

The Docker Registry container exposes the following methods:
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ nav:
- modules/pulsar.md
- modules/redis.md
- modules/redpanda.md
- modules/dockerregistry.md
Copy link
Member

Choose a reason for hiding this comment

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

- modules/vault.md
- Examples:
- examples/index.md
Expand Down
5 changes: 5 additions & 0 deletions modules/dockerregistry/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
include ../../commons-test.mk

.PHONY: test
test:
$(MAKE) test-dockerregistry
96 changes: 96 additions & 0 deletions modules/dockerregistry/dockerregistry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package dockerregistry

import (
"context"

"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
)

// DockerRegistryContainer represents the DockerRegistry container type used in the module
type DockerRegistryContainer struct {
testcontainers.Container
}

// RunContainer creates an instance of the DockerRegistry container type
func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*DockerRegistryContainer, error) {
req := testcontainers.ContainerRequest{
Image: "registry:2",
ExposedPorts: []string{"5000:5000/tcp"},
Copy link
Member

Choose a reason for hiding this comment

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

I think we do not want to always force a fixed port for the container:

Suggested change
ExposedPorts: []string{"5000:5000/tcp"},
ExposedPorts: []string{"5000/tcp"},

WaitingFor: wait.ForExposedPort(),
}

genericContainerReq := testcontainers.GenericContainerRequest{
ContainerRequest: req,
Started: true,
}

for _, opt := range opts {
opt.Customize(&genericContainerReq)
}

container, err := testcontainers.GenericContainer(ctx, genericContainerReq)
if err != nil {
return nil, err
}

return &DockerRegistryContainer{Container: container}, nil
}

// WithAuthentication customizer that will retrieve a htpasswd file into the htpasswd directory given in input
func WithAuthentication(htpasswdPath string) testcontainers.CustomizeRequestOption {
return func(req *testcontainers.GenericContainerRequest) {
if req.Env == nil {
req.Env = make(map[string]string)
}

req.Env["REGISTRY_AUTH"] = "htpasswd"
req.Env["REGISTRY_AUTH_HTPASSWD_REALM"] = "Registry"
req.Env["REGISTRY_AUTH_HTPASSWD_PATH"] = "/auth/htpasswd"

if req.Mounts == nil {
req.Mounts = testcontainers.ContainerMounts{}
}

htpasswdMount := testcontainers.ContainerMount{
Source: testcontainers.GenericBindMountSource{
HostPath: htpasswdPath,
},
Target: "/auth",
}
req.Mounts = append(req.Mounts, htpasswdMount)
}

}

// WithData customizer that will retrieve a data directory and mount it inside the registry container
Copy link
Member

Choose a reason for hiding this comment

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

Do we need a Docker mount for it? I wonder if copying the files/dir into the container, using the req.Files attribute would be something to consider.

@eddumelendez is there a preference when creating modules: using mounts or just copying files before the container start? 🤔

Copy link
Member

Choose a reason for hiding this comment

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

The preference is to copy files.

Copy link
Member

Choose a reason for hiding this comment

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

@davidesalerno then I'd advocate for converting all the Mounts into Files 🙏

func WithData(dataDir string) testcontainers.CustomizeRequestOption {
return func(req *testcontainers.GenericContainerRequest) {
if req.Env == nil {
req.Env = make(map[string]string)
}

req.Env["REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY"] = "/data"

if req.Mounts == nil {
req.Mounts = testcontainers.ContainerMounts{}
}

dataMount := testcontainers.ContainerMount{
Source: testcontainers.GenericBindMountSource{
HostPath: dataDir,
},
Target: "/data",
}

req.Mounts = append(req.Mounts, dataMount)

}
}

// WithImage customizer that will override the registry image used
func WithImage(image string) testcontainers.CustomizeRequestOption {
return func(req *testcontainers.GenericContainerRequest) {
req.Image = image
}
}
Comment on lines +91 to +96
Copy link
Member

Choose a reason for hiding this comment

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

The core library already exposes a testcontainers.WithImage option, which can be used in the modules.

Suggested change
// WithImage customizer that will override the registry image used
func WithImage(image string) testcontainers.CustomizeRequestOption {
return func(req *testcontainers.GenericContainerRequest) {
req.Image = image
}
}

Loading