Skip to content

Commit

Permalink
[feat] add pull-through registry support
Browse files Browse the repository at this point in the history
  • Loading branch information
DerekTBrown committed Nov 27, 2024
1 parent 5282f72 commit 658329d
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 0 deletions.
16 changes: 16 additions & 0 deletions pkg/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,17 @@ type TypeMeta struct {
APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"`
}

// PullThroughRegistry contains configuration for pull-through registries
type PullThroughRegistry struct {
// The FQDN of the registry (i.e. docker.io)
RegistryFQDN string `json:"registryFQDN,omitempty" yaml:"registryFQDN,omitempty"`

// The RemoteURL of the registry (i.e. https://registry-1.docker.io)
RemoteURL string `json:"remoteURL,omitempty" yaml:"remoteURL,omitempty"`
Username string `json:"username,omitempty" yaml:"username,omitempty"`
Password string `json:"password,omitempty" yaml:"password,omitempty"`
}

// Cluster contains cluster configuration.
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type Cluster struct {
Expand All @@ -42,6 +53,11 @@ type Cluster struct {
// Not supported on all cluster products.
Registry string `json:"registry,omitempty" yaml:"registry,omitempty"`

// A list of pull-through registries to configure on the cluster.
//
// Not supported on all cluster products.
PullThroughRegistries []PullThroughRegistry `json:"pullThroughRegistries,omitempty" yaml:"pullThroughRegistries,omitempty"`

// The desired version of Kubernetes to run.
//
// Examples:
Expand Down
3 changes: 3 additions & 0 deletions pkg/cluster/admin_docker_desktop.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ func (a *dockerDesktopAdmin) Create(ctx context.Context, desired *api.Cluster, r
if registry != nil {
return fmt.Errorf("ctlptl currently does not support connecting a registry to docker-desktop")
}
if len(desired.PullThroughRegistries) > 0 {
return fmt.Errorf("ctlptl currently does not support connecting pull-through registries to minikube")
}

isLocalDockerDesktop := docker.IsLocalDockerDesktop(a.host, a.os)
if !isLocalDockerDesktop {
Expand Down
3 changes: 3 additions & 0 deletions pkg/cluster/admin_k3d.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ func (a *k3dAdmin) Create(ctx context.Context, desired *api.Cluster, registry *a
if registry != nil {
klog.V(3).Infof("Initializing cluster with registry config:\n%+v\n---\n", registry)
}
if len(desired.PullThroughRegistries) > 0 {
return fmt.Errorf("ctlptl currently does not support connecting pull-through registries to minikube")
}

k3dV, err := a.version(ctx)
if err != nil {
Expand Down
20 changes: 20 additions & 0 deletions pkg/cluster/admin_kind.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,26 @@ func (a *kindAdmin) kindClusterConfig(desired *api.Cluster, registry *api.Regist
kindConfig.ContainerdConfigPatches = append(kindConfig.ContainerdConfigPatches, patch)
}
}

for _, reg := range desired.PullThroughRegistries {
// Add the registry to the list of mirrors.
patch := fmt.Sprintf(`[plugins."io.containerd.grpc.v1.cri".registry.mirrors."%s"]
endpoint = ["http://%s"]
`, reg.RegistryFQDN, reg.RemoteURL)
kindConfig.ContainerdConfigPatches = append(kindConfig.ContainerdConfigPatches, patch)

// Specify the auth for the registry, if provided.
if reg.Username != "" || reg.Password != "" {
passwordValue := os.ExpandEnv(reg.Password)

patch := fmt.Sprintf(`[plugins."io.containerd.grpc.v1.cri".registry.configs."%s".auth]
username = "%s"
password = "%s"
`, reg.RegistryFQDN, reg.Username, passwordValue)
kindConfig.ContainerdConfigPatches = append(kindConfig.ContainerdConfigPatches, patch)
}
}

return kindConfig
}

Expand Down
36 changes: 36 additions & 0 deletions pkg/cluster/admin_kind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,39 @@ kind-control-plane2
"kind-control-plane2",
}, nodeExec)
}

func TestKindClusterConfigWithPullThroughRegistries(t *testing.T) {
iostreams := genericclioptions.IOStreams{
In: os.Stdin,
Out: os.Stdout,
ErrOut: os.Stderr,
}
runner := exec.NewFakeCmdRunner(func(argv []string) string {
return ""
})
a := newKindAdmin(iostreams, runner, &fakeDockerClient{})

desired := &api.Cluster{
PullThroughRegistries: []api.PullThroughRegistry{
{
RegistryFQDN: "example.com",
RemoteURL: "example.com:5000",
Username: "user",
Password: "pass",
},
},
}

kindConfig := a.kindClusterConfig(desired, nil, containerdRegistryV2)

expectedMirror := `[plugins."io.containerd.grpc.v1.cri".registry.mirrors."example.com"]
endpoint = ["http://example.com:5000"]
`
expectedAuth := `[plugins."io.containerd.grpc.v1.cri".registry.configs."example.com".auth]
username = "user"
password = "pass"
`

assert.Contains(t, kindConfig.ContainerdConfigPatches, expectedMirror)
assert.Contains(t, kindConfig.ContainerdConfigPatches, expectedAuth)
}
3 changes: 3 additions & 0 deletions pkg/cluster/admin_minikube.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ func (a *minikubeAdmin) Create(ctx context.Context, desired *api.Cluster, regist
if registry != nil {
klog.V(3).Infof("Initializing cluster with registry config:\n%+v\n---\n", registry)
}
if len(desired.PullThroughRegistries) > 0 {
return fmt.Errorf("ctlptl currently does not support connecting pull-through registries to minikube")
}

v, err := a.version(ctx)
if err != nil {
Expand Down

0 comments on commit 658329d

Please sign in to comment.