-
Notifications
You must be signed in to change notification settings - Fork 9
/
k3dregistry.go
114 lines (94 loc) · 3.97 KB
/
k3dregistry.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// Copyright 2022 Namespace Labs Inc; All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
package k3d
import (
"context"
"fmt"
"strings"
"namespacelabs.dev/foundation/internal/artifacts/oci"
"namespacelabs.dev/foundation/internal/artifacts/registry"
"namespacelabs.dev/foundation/internal/build/buildkit"
"namespacelabs.dev/foundation/internal/compute"
"namespacelabs.dev/foundation/internal/fnerrors"
"namespacelabs.dev/foundation/internal/runtime/docker"
"namespacelabs.dev/foundation/internal/tcache"
"namespacelabs.dev/foundation/std/cfg"
)
var confConfigType = cfg.DefineConfigType[*Configuration]()
type k3dRegistry struct {
ContainerName string
PublicPort string
ContainerIPAddress string
}
var registries = tcache.NewCache[*k3dRegistry]()
var _ registry.Manager = &k3dRegistry{}
var _ buildkit.BuildkitAwareRegistry = &k3dRegistry{}
var _ oci.TargetRewritter = &k3dRegistry{}
func Register() {
registry.Register("k3d", func(ctx context.Context, ck cfg.Configuration) (registry.Manager, error) {
conf, ok := confConfigType.CheckGet(ck)
if !ok {
return nil, fnerrors.BadInputError("can't use a k3d registry without a k3d configuration")
}
return registries.Compute(conf.RegistryContainerName, func() (*k3dRegistry, error) {
client, err := docker.NewClient()
if err != nil {
return nil, err
}
inspected, err := client.ContainerInspect(ctx, conf.RegistryContainerName)
if err != nil {
return nil, fnerrors.InternalError("failed to inspect k3d registry: %w", err)
}
if inspected.NetworkSettings == nil || inspected.NetworkSettings.Networks["bridge"] == nil {
return nil, fnerrors.InternalError("missing network configuration in k3d registry container")
}
if len(inspected.NetworkSettings.Ports["5000/tcp"]) == 0 {
return nil, fnerrors.InternalError("missing port configuration in k3d registry container")
}
return &k3dRegistry{
ContainerName: conf.RegistryContainerName,
PublicPort: inspected.NetworkSettings.Ports["5000/tcp"][0].HostPort,
ContainerIPAddress: inspected.NetworkSettings.Networks["bridge"].IPAddress,
}, nil
})
})
}
func (r *k3dRegistry) Access() oci.RegistryAccess { return oci.RegistryAccess{InsecureRegistry: true} }
func (r *k3dRegistry) baseUrl() string {
return fmt.Sprintf("%s:%s", r.ContainerName, r.PublicPort)
}
func (r *k3dRegistry) AllocateName(repository string) compute.Computable[oci.AllocatedRepository] {
return registry.AllocateStaticName(r, r.baseUrl(), repository, r.Access())
}
func (r *k3dRegistry) AttachKeychain(img oci.ImageID) (oci.AllocatedRepository, error) {
return registry.AttachStaticKeychain(r, img, r.Access()), nil
}
func (r *k3dRegistry) CheckExportRequest(cli *buildkit.GatewayClient, name oci.AllocatedRepository) (*buildkit.ExportToRegistryRequest, *buildkit.ExportToRegistryRequest) {
// There are some assumptions baked into this that are not verified at
// runtime, notably that buildkit and the registry are deployed to the same
// docker instance.
if cli.UsesDocker() {
trimmed := strings.TrimPrefix(name.Repository, r.baseUrl())
if trimmed != name.Repository {
return &buildkit.ExportToRegistryRequest{
// Connect directly to the registry via localhost.
Name: fmt.Sprintf("127.0.0.1:%s%s", r.PublicPort, trimmed),
Insecure: r.Access().InsecureRegistry,
},
&buildkit.ExportToRegistryRequest{
// Connect directly to the registry via the default bridge.
Name: fmt.Sprintf("%s:5000%s", r.ContainerIPAddress, trimmed),
Insecure: r.Access().InsecureRegistry,
}
}
}
return nil, nil
}
func (r *k3dRegistry) CheckRewriteLocalUse(target oci.TargetRepository) *oci.TargetRepository {
if x := strings.TrimPrefix(target.ImageID.Repository, r.baseUrl()+"/"); x != target.ImageID.Repository {
target.ImageID.Repository = fmt.Sprintf("127.0.0.1:%s/%s", r.PublicPort, x)
return &target
}
return nil
}