Skip to content

Commit

Permalink
use docker login for registries
Browse files Browse the repository at this point in the history
  • Loading branch information
damoon committed Nov 11, 2020
1 parent fe1f513 commit fb17f10
Show file tree
Hide file tree
Showing 11 changed files with 535 additions and 108 deletions.
29 changes: 12 additions & 17 deletions Tiltfile
Original file line number Diff line number Diff line change
Expand Up @@ -59,25 +59,20 @@ k8s_resource(
resource_deps=['setup-s3-bucket'],
)

local_resource ('use case 1',
local_resource ('docker build',
'DOCKER_HOST=tcp://127.0.0.1:12376 docker build ./use-case-1',
resource_deps=['wedding'] ,
resource_deps=['wedding'],
)

local_resource ('use case 3',
'cd use-case-3 && DOCKER_HOST=tcp://127.0.0.1:12376 tilt ci --port 0',
resource_deps=['wedding'] ,
local_resource ('docker pull tag push',
'DOCKER_HOST=tcp://127.0.0.1:12376 docker pull alpine && \
DOCKER_HOST=tcp://127.0.0.1:12376 docker tag alpine wedding-registry:5000/alpine-retag && \
DOCKER_HOST=tcp://127.0.0.1:12376 docker push wedding-registry:5000/alpine-retag',
resource_deps=['wedding'],
)


#k8s_yaml('e2e-tests/deployment/tests.yaml')
#docker_build(
# 'e2e-tests-image',
# 'e2e-tests',
# dockerfile='e2e-tests/deployment/Dockerfile',
#)
#k8s_resource(
# 'e2e-tests',
# trigger_mode=TRIGGER_MODE_MANUAL,
# resource_deps=['backend', 'frontend'],
#)
local_resource ('tilt ci',
'cd use-case-3 && DOCKER_HOST=tcp://127.0.0.1:12376 tilt ci --port 0 && \
tilt down',
resource_deps=['wedding'],
)
154 changes: 100 additions & 54 deletions pkg/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package wedding

import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
Expand Down Expand Up @@ -33,9 +32,9 @@ type buildConfig struct {
dockerfile string
memoryBytes int
target string
tag string
tags []string
noCache bool
registryAuth string
registryAuth dockerConfig
contextFilePath string
}

Expand All @@ -45,37 +44,35 @@ type ObjectStore struct {
Bucket string
}

func (s Service) buildHandler() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
func (s Service) build(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

cfg, err := buildParameters(r)
if err != nil {
printBuildHelpText(w, err)
return
}

err = s.objectStore.storeContext(ctx, r, cfg)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("store context: %v", err)))
log.Printf("execute build: %v", err)
return
}
defer func() {
s.objectStore.deleteContext(ctx, cfg)
}()
cfg, err := buildParameters(r)
if err != nil {
printBuildHelpText(w, err)
return
}

err = s.executeBuild(ctx, cfg, w)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("execute build: %v", err)))
log.Printf("execute build: %v", err)
return
}
err = s.objectStore.storeContext(ctx, r, cfg)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("store context: %v", err)))
log.Printf("execute build: %v", err)
return
}
defer func() {
s.objectStore.deleteContext(ctx, cfg)
}()

w.Write([]byte(`{"aux":{"ID":"sha256:d8f38feb768dd84819b607224c07f2453412e1808b4b4e52894048073e50732d"}}`))
err = s.executeBuild(ctx, cfg, w)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("execute build: %v", err)))
log.Printf("execute build: %v", err)
return
}

w.Write([]byte(`{"aux":{"ID":"sha256:42341736246f8e99122d49e4c0e414f0a3e5f69a024e72a2ac1a39a2093d483f"}}`))
}

func buildParameters(r *http.Request) (*buildConfig, error) {
Expand Down Expand Up @@ -189,27 +186,20 @@ func buildParameters(r *http.Request) (*buildConfig, error) {
cfg.target = r.URL.Query().Get("target")

// image tag
tags := r.URL.Query()["t"]
if len(tags) > 1 {
return cfg, fmt.Errorf("wedding does not support setting multiple image tags at a time")
}
// if len(tags) != 1 {
// return cfg, fmt.Errorf("image tag not set")
// }
if len(tags) == 1 {
cfg.tag = tags[0]
}
cfg.tags = r.URL.Query()["t"]

// disable cache
nocache := r.URL.Query().Get("nocache")
cfg.noCache = nocache == "1"

// registry authentitation
registryCfg, err := base64.StdEncoding.DecodeString(r.Header.Get("X-Registry-Config"))
log.Printf("X-Registry-Config: %v", r.Header.Get("X-Registry-Config"))
dockerCfg, err := xRegistryConfig(r.Header.Get("X-Registry-Config")).toDockerConfig()
if err != nil {
return cfg, fmt.Errorf("decode registry authentication config: %v", err)
return cfg, fmt.Errorf("extract registry config: %v", err)
}
cfg.registryAuth = string(registryCfg)

cfg.registryAuth = dockerCfg

return cfg, nil
}
Expand Down Expand Up @@ -287,11 +277,53 @@ func (o ObjectStore) deleteContext(ctx context.Context, cfg *buildConfig) error

func (s Service) executeBuild(ctx context.Context, cfg *buildConfig, w http.ResponseWriter) error {

stream(w, fmt.Sprintf("%v", cfg))

presignedContextURL, err := s.objectStore.presignContext(cfg)
if err != nil {
return err
}

secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "wedding-docker-config-",
},
StringData: map[string]string{
"config.json": cfg.registryAuth.mustToJSON(),
},
}

secretClient := s.kubernetesClient.CoreV1().Secrets(s.namespace)

secret, err = secretClient.Create(ctx, secret, metav1.CreateOptions{})
if err != nil {
streamf(w, "Secret creation failed: %v\n", err)
return fmt.Errorf("create secret: %v", err)
}
defer func() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

err = secretClient.Delete(ctx, secret.Name, metav1.DeleteOptions{})
if err != nil {
streamf(w, "Secret deletetion failed: %v\n", err)
log.Printf("delete secret: %v", err)
}
}()

imageNames := ""
for idx, tag := range cfg.tags {
if idx != 0 {
imageNames += ","
}
imageNames += fmt.Sprintf("wedding-registry:5000/images/%s", tag)
}

output := "--output type=image,push=true,name=wedding-registry:5000/digests"
if imageNames != "" {
output = fmt.Sprintf("--output type=image,push=true,name=\"%s\"", imageNames)
}

// TODO add timeout for script
buildScript := fmt.Sprintf(`
set -euo pipefail
Expand All @@ -300,7 +332,7 @@ mkdir ~/context && cd ~/context
mkdir -p ~/.config/buildkit/
echo "
[registry.\"cache-registry:5000\"]
[registry.\"wedding-registry:5000\"]
http = true
insecure = true
" > ~/.config/buildkit/buildkitd.toml
Expand All @@ -316,10 +348,12 @@ buildctl-daemonless.sh \
--local context=. \
--local dockerfile=. \
--opt filename=Dockerfile \
--output type=image,push=true,name=cache-registry:5000/cache-repo:latest \
--export-cache=type=registry,ref=cache-registry:5000/cache-repo,mode=max \
--import-cache=type=registry,ref=cache-registry:5000/cache-repo
`, presignedContextURL)
%s \
--export-cache=type=registry,ref=wedding-registry:5000/cache-repo,mode=max \
--import-cache=type=registry,ref=wedding-registry:5000/cache-repo
`, presignedContextURL, output)

stream(w, buildScript)

pod := &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Expand All @@ -328,16 +362,28 @@ buildctl-daemonless.sh \
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "buildkit",
Image: "moby/buildkit:master-rootless",
ImagePullPolicy: corev1.PullAlways,
// Image: "moby/buildkit:v0.8-beta",
// Image: "moby/buildkit:v0.7.2-rootless",
Name: "buildkit",
Image: "moby/buildkit:v0.7.2-rootless",
Command: []string{
"sh",
"-c",
buildScript,
// "date; sleep 1; date; sleep 1; date; sleep 1; date;",
},
VolumeMounts: []corev1.VolumeMount{
{
MountPath: "/home/user/.docker",
Name: "docker-config",
},
},
},
},
Volumes: []corev1.Volume{
{
Name: "docker-config",
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: secret.Name,
},
},
},
},
Expand Down
9 changes: 6 additions & 3 deletions pkg/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func (s Service) executePod(ctx context.Context, pod *corev1.Pod, w http.ResponseWriter) error {
func (s Service) executePod(ctx context.Context, pod *corev1.Pod, w io.Writer) error {
podClient := s.kubernetesClient.CoreV1().Pods(s.namespace)

stream(w, "Creating new pod.\n")
Expand Down Expand Up @@ -88,6 +88,9 @@ printLogs:
if err != nil {
if err == io.EOF {
stream(w, "End of logs reached.\n")
if failed {
return fmt.Errorf("pod failed")
}
return nil
}

Expand All @@ -107,7 +110,7 @@ func (s Service) podStatus(ctx context.Context, podName string) (corev1.PodPhase
return pod.Status.Phase, nil
}

func stream(w http.ResponseWriter, message string) error {
func stream(w io.Writer, message string) error {
b, err := json.Marshal(message)
if err != nil {
panic(err) // encode a string to json should not fail
Expand All @@ -127,6 +130,6 @@ func stream(w http.ResponseWriter, message string) error {
return nil
}

func streamf(w http.ResponseWriter, message string, args ...interface{}) error {
func streamf(w io.Writer, message string, args ...interface{}) error {
return stream(w, fmt.Sprintf(message, args...))
}
Loading

0 comments on commit fb17f10

Please sign in to comment.