diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..22d0d82f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +vendor diff --git a/docker-host/Dockerfile b/docker-host/Dockerfile index f859d14c..4c9eac35 100644 --- a/docker-host/Dockerfile +++ b/docker-host/Dockerfile @@ -1,5 +1,15 @@ -FROM uselagoon/commons:latest as commons +FROM golang:1.22-alpine3.20 AS builder +WORKDIR /build + +COPY main.go . +COPY go.mod . +COPY go.sum . + +# compile +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build docker-host . + +FROM uselagoon/commons:latest AS commons FROM docker:27.0.3-dind LABEL org.opencontainers.image.authors="The Lagoon Authors" maintainer="The Lagoon Authors" @@ -11,6 +21,8 @@ COPY --from=commons /bin/fix-permissions /bin/ep /bin/docker-sleep /bin/ COPY --from=commons /sbin/tini /sbin/ COPY --from=commons /home /home +COPY --from=builder /build/docker-host /docker-host + ENV TMPDIR=/tmp \ TMP=/tmp \ HOME=/home \ @@ -23,17 +35,12 @@ RUN apk add --no-cache bash ENV DOCKER_HOST=docker-host \ REGISTRY=docker-registry.default.svc:5000 \ - REPOSITORY_TO_UPDATE=amazeeio \ + REPOSITORIES_TO_UPDATE=*uselagoon/*:* \ BIP=172.16.0.1/16 \ REGISTRY_MIRROR=https://imagecache.amazeeio.cloud RUN fix-permissions /home -COPY update-push-images.sh /update-push-images.sh -COPY update-images.sh /update-images.sh -COPY prune-images.sh /prune-images.sh -COPY remove-exited.sh /remove-exited.sh - ENTRYPOINT ["/sbin/tini", "--", "/lagoon/entrypoints.sh"] -CMD ["sh", "-c", "sh /usr/local/bin/dind /usr/local/bin/dockerd --host=tcp://0.0.0.0:2375 --host=unix:///var/run/docker.sock --insecure-registry=${REGISTRY} --insecure-registry=harbor-harbor-core.harbor.svc.cluster.local:80 --bip=${BIP} --storage-driver=overlay2 --registry-mirror=${REGISTRY_MIRROR}"] +CMD ["sh", "-c", "/docker-host"] diff --git a/docker-host/go.mod b/docker-host/go.mod new file mode 100644 index 00000000..76c2f79e --- /dev/null +++ b/docker-host/go.mod @@ -0,0 +1,36 @@ +module docker-host + +go 1.22 + +require ( + github.com/docker/docker v27.2.0+incompatible + github.com/robfig/cron/v3 v3.0.1 + github.com/uselagoon/machinery v0.0.29 +) + +require ( + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect + go.opentelemetry.io/otel v1.29.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0 // indirect + go.opentelemetry.io/otel/metric v1.29.0 // indirect + go.opentelemetry.io/otel/sdk v1.29.0 // indirect + go.opentelemetry.io/otel/trace v1.29.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/time v0.3.0 // indirect + gotest.tools/v3 v3.4.0 // indirect +) diff --git a/docker-host/go.sum b/docker-host/go.sum new file mode 100644 index 00000000..764b4780 --- /dev/null +++ b/docker-host/go.sum @@ -0,0 +1,123 @@ +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v27.2.0+incompatible h1:Rk9nIVdfH3+Vz4cyI/uhbINhEZ/oLmc+CBXmH6fbNk4= +github.com/docker/docker v27.2.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/uselagoon/machinery v0.0.29 h1:invFIPv1Z1xCt8/1ilbiNDuAEPrb+AUO21BnNG+CX8c= +github.com/uselagoon/machinery v0.0.29/go.mod h1:X0qguIO9skumMhhT0ap5CKHulKgYzy3TiIn+xlwiFQc= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= +go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= +go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 h1:dIIDULZJpgdiHz5tXrTgKIMLkus6jEFa7x5SOKcyR7E= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0/go.mod h1:jlRVBe7+Z1wyxFSUs48L6OBQZ5JwH2Hg/Vbl+t9rAgI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0 h1:JAv0Jwtl01UFiyWZEMiJZBiTlv5A50zNs8lsthXqIio= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0/go.mod h1:QNKLmUEAq2QUbPQUfvw4fmv0bgbK7UlOSFCnXyfvSNc= +go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= +go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= +go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo= +go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok= +go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= +go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd h1:BBOTEWLuuEGQy9n1y9MhVJ9Qt0BDu21X8qZs71/uPZo= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= +gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= diff --git a/docker-host/main.go b/docker-host/main.go new file mode 100644 index 00000000..1c1d1214 --- /dev/null +++ b/docker-host/main.go @@ -0,0 +1,273 @@ +package main + +import ( + "context" + "fmt" + "io" + "log" + "os" + "os/exec" + "strings" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/api/types/image" + "github.com/docker/docker/client" + "github.com/robfig/cron/v3" + machineryvars "github.com/uselagoon/machinery/utils/variables" +) + +const EnvOverrideHost = "DOCKER_HOST" + +var dockerHost = machineryvars.GetEnv("DOCKER_HOST", "docker-host") +var repositoriesToUpdate = machineryvars.GetEnv("REPOSITORIES_TO_UPDATE", "uselagoon") +var registry = machineryvars.GetEnv("REGISTRY", "docker-registry.default.svc:5000") +var bip = machineryvars.GetEnv("BIP", "172.16.0.1/16") +var logLevel = machineryvars.GetEnv("LOG_LEVEL", "info") +var registryMirror = machineryvars.GetEnv("REGISTRY_MIRROR", "") +var pruneImagesSchedule = machineryvars.GetEnv("PRUNE_SCHEDULE", "22 1 * * *") +var pruneDanglingSchedule = machineryvars.GetEnv("PRUNE_DANGLING_SCHEDULE", "22 1 * * *") +var pruneBuilderCacheSchedule = machineryvars.GetEnv("PRUNE_BUILDER_CACHE_SCHEDULE", "22 1 * * *") +var removeExitedSchedule = machineryvars.GetEnv("REMOVE_EXITED_SCHEDULE", "22 */4 * * *") +var updateImagesSchedule = machineryvars.GetEnv("UPDATE_IMAGES_SCHEDULE", "*/15 * * * *") +var pruneImagesUntil = machineryvars.GetEnv("PRUNE_IMAGES_UNTIL", "168h") +var pruneBuilderCacheUntil = machineryvars.GetEnv("PRUNE_BUILDER_CACHE_UNTIL", "168h") + +func main() { + cli, err := client.NewClientWithOpts( + client.WithHostFromEnv(), + client.WithAPIVersionNegotiation(), + ) + if err != nil { + log.Fatalf("Error: %v", err) + } + defer cli.Close() + + var command = fmt.Sprintf("/usr/local/bin/dind /usr/local/bin/dockerd --host=tcp://0.0.0.0:2375 --host=unix:///var/run/docker.sock --bip=%s --storage-driver=overlay2 --tls=false --log-level=%s", bip, logLevel) + if registry != "" { + command = command + fmt.Sprintf(" --insecure-registry=%s", registry) + } + if registryMirror != "" { + command = command + fmt.Sprintf(" --registry-mirror=%s", registryMirror) + } + var cmd = exec.Command("sh", "-c", command) + + if dockerHost != cli.DaemonHost() { + log.Fatalf("Could not connect to %s", dockerHost) + } + c := cron.New() + pruneImages(cli, c) + pruneDanglingImages(cli, c) + pruneBuilderCache(cli, c) + removeExited(cli, c) + updateImages(cli, c) + c.Start() + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + log.Fatalf("could not run command: %v", err) + } +} + +func pruneImages(client *client.Client, c *cron.Cron) { + _, err := c.AddFunc(pruneImagesSchedule, func() { + log.Println("Starting image prune") + ageFilter := filters.NewArgs() + ageFilter.Add("until", pruneImagesUntil) + + // prune all images older than 7 days or what is specified in the environment variable + pruneReport, err := client.ImagesPrune(context.Background(), ageFilter) + if err != nil { + log.Println(err) + return + } + log.Printf("Image prune complete: %d images deleted, %d bytes reclaimed\n", + len(pruneReport.ImagesDeleted), pruneReport.SpaceReclaimed) + }) + + if err != nil { + log.Printf("Error initiating pruneImages cron: %v\n", err) + } +} + +func pruneDanglingImages(client *client.Client, c *cron.Cron) { + _, err := c.AddFunc(pruneDanglingSchedule, func() { + log.Println("Starting dangling image prune") + pruneDanglingFilter := filters.NewArgs() + pruneDanglingFilter.Add("dangling", "true") + + // Cleans up dangling images + pruneReport, pruneErr := client.ImagesPrune(context.Background(), pruneDanglingFilter) + if pruneErr != nil { + log.Println(pruneErr) + } + log.Printf("Dangling Image prune complete: %d images deleted, %d bytes reclaimed\n", + len(pruneReport.ImagesDeleted), pruneReport.SpaceReclaimed) + }) + + if err != nil { + log.Printf("Error initiating pruneDanglingImages cron: %v\n", err) + } +} + +func pruneBuilderCache(client *client.Client, c *cron.Cron) { + _, err := c.AddFunc(pruneBuilderCacheSchedule, func() { + log.Println("Starting builder cache prune") + ageFilter := filters.NewArgs() + ageFilter.Add("until", pruneBuilderCacheUntil) + builderCacheOpts := types.BuildCachePruneOptions{ + Filters: ageFilter, + } + + // Cleans up build cache images + pruneReport, pruneErr := client.BuildCachePrune(context.Background(), builderCacheOpts) + if pruneErr != nil { + log.Println(pruneErr) + } + log.Printf("Builder Cache prune complete: %d deleted, %d bytes reclaimed\n", + len(pruneReport.CachesDeleted), pruneReport.SpaceReclaimed) + }) + + if err != nil { + log.Printf("Error initiating pruneBuilderCache cron: %v\n", err) + } +} + +func removeExited(client *client.Client, c *cron.Cron) { + _, err := c.AddFunc(removeExitedSchedule, func() { + log.Println("Starting removeExited") + ctx := context.Background() + statusFilter := filters.NewArgs() + statusFilter.Add("status", "paused") + statusFilter.Add("status", "exited") + statusFilter.Add("status", "dead") + statusFilter.Add("status", "created") + containers, err := client.ContainerList(ctx, container.ListOptions{ + Filters: statusFilter, + }) + if err != nil { + log.Println(err) + return + } + + // remove all exited containers + for _, con := range containers { + err := client.ContainerRemove(ctx, con.ID, container.RemoveOptions{ + Force: true, + RemoveVolumes: true, + }) + if err != nil { + log.Println(err) + } + } + log.Println("removeExited complete") + }) + + if err != nil { + log.Printf("Error initiating removeExited cron: %v\n", err) + } +} + +func updateImages(client *client.Client, c *cron.Cron) { + _, err := c.AddFunc(updateImagesSchedule, func() { + log.Println("Starting update images") + ctx := context.Background() + ImgFilters := addFilters(repositoriesToUpdate) + preUpdateImages, err := client.ImageList(ctx, image.ListOptions{Filters: ImgFilters}) + if err != nil { + log.Println(err) + return + } + + var preUpdateIDs []string + for _, img := range preUpdateImages { + preUpdateIDs = append(preUpdateIDs, img.ID) + } + + var imgRepoTags []string + for _, img := range preUpdateImages { + if img.RepoTags != nil { + imgRepoTags = append(imgRepoTags, img.RepoTags...) + } + } + + // Iterates through all images that have the name of the repository we are interested in it + for _, img := range imgRepoTags { + out, err := client.ImagePull(ctx, img, image.PullOptions{}) + + if err != nil { + log.Println(err) + continue + } + defer out.Close() + _, error := io.Copy(io.Discard, out) + if error != nil { + log.Println(err) + } + } + + postUpdateImages, err := client.ImageList(ctx, image.ListOptions{Filters: ImgFilters}) + if err != nil { + log.Println(err) + } + + var postUpdateIDs []string + for _, img := range postUpdateImages { + postUpdateIDs = append(postUpdateIDs, img.ID) + } + + updatedImages := imgComparison(preUpdateIDs, postUpdateIDs) + for _, img := range postUpdateImages { + for _, updatedImg := range updatedImages { + if img.ID == updatedImg { + log.Printf("Updated image %s", img.RepoTags) + } + } + } + + imgPluralize := "" + if len(updatedImages) == 1 { + imgPluralize = "image" + } else { + imgPluralize = "images" + } + log.Printf("Update images complete | %d %s updated", len(updatedImages), imgPluralize) + }) + + if err != nil { + log.Printf("Error initiating updateImages cron: %v\n", err) + } +} + +func imgComparison(preUpdate, postUpdate []string) []string { + var updatedImgs []string + + for i := 0; i < 2; i++ { + for _, preUpdateImg := range preUpdate { + found := false + for _, postUpdateImg := range postUpdate { + if preUpdateImg == postUpdateImg { + found = true + break + } + } + if !found { + updatedImgs = append(updatedImgs, preUpdateImg) + } + } + if i == 0 { + preUpdate, postUpdate = postUpdate, preUpdate + } + } + return updatedImgs +} + +func addFilters(repo string) filters.Args { + repoFilters := filters.NewArgs() + splitRepos := strings.Split(repo, "|") + for _, repo := range splitRepos { + repoFilters.Add("reference", repo) + } + return repoFilters +} diff --git a/docker-host/prune-images.sh b/docker-host/prune-images.sh deleted file mode 100755 index a07a2118..00000000 --- a/docker-host/prune-images.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -set -x -if ! docker -H ${DOCKER_HOST} info &> /dev/null; then - echo "could not connect to ${DOCKER_HOST}"; exit 1 -fi - -# prune all images older than 7 days or what is specified in the environment variable -docker image prune -af --filter "until=${PRUNE_IMAGES_UNTIL:-168h}" - -# prune docker build caches coming from buildkit builds -# prune all docker build cache images older than 7 days or what is specified in the environment variable -docker builder prune -af --filter "until=${PRUNE_IMAGES_UNTIL:-168h}" - -# after old images are pruned, clean up dangling images -docker image prune -f diff --git a/docker-host/remove-exited.sh b/docker-host/remove-exited.sh deleted file mode 100755 index 319810f7..00000000 --- a/docker-host/remove-exited.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -set -x -if ! docker -H ${DOCKER_HOST} info &> /dev/null; then - echo "could not connect to ${DOCKER_HOST}"; exit 1 -fi - -# remove all exited containers -docker ps -a | grep Exit | cut -d ' ' -f 1 | xargs docker rm diff --git a/docker-host/update-images.sh b/docker-host/update-images.sh deleted file mode 100755 index 0de8fbba..00000000 --- a/docker-host/update-images.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -e -set -x - -if ! docker -H ${DOCKER_HOST} info &> /dev/null; then - echo "could not connect to ${DOCKER_HOST}"; exit 1 -fi - -# Iterates through all images that have the name of the repository we are interested in in it -for FULL_IMAGE in $(docker image ls --format "{{.Repository}}:{{.Tag}}" | grep -E "${REPOSITORY_TO_UPDATE}/" | grep -v none); do - # pull newest version of found image - docker pull ${FULL_IMAGE} | cat -done diff --git a/docker-host/update-push-images.sh b/docker-host/update-push-images.sh deleted file mode 100755 index c75b3acf..00000000 --- a/docker-host/update-push-images.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -e -set -x -NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) - -if ! docker -H ${DOCKER_HOST} info &> /dev/null; then - echo "could not connect to ${DOCKER_HOST}"; exit 1 -fi - -docker login -u=serviceaccount --password-stdin ${REGISTRY} < /var/run/secrets/kubernetes.io/serviceaccount/token - -# Iterates through all images that have the name of the repository we are interested in in it -for FULL_IMAGE in $(docker image ls --format "{{.Repository}}:{{.Tag}}" | grep -E "${REPOSITORY_TO_UPDATE}/" | grep -v none); do - IMAGE=(${FULL_IMAGE//// }) - if [ ${#IMAGE[@]} == "3" ]; then - IMAGE_NO_REPOSITORY=${IMAGE[2]} - else - IMAGE_NO_REPOSITORY=${IMAGE[1]} - fi - - # pull newest version of found image - docker pull ${FULL_IMAGE} | cat - # Tag the image with the openshift registry name and the openshift project this container is running - docker tag ${FULL_IMAGE} ${REGISTRY}/${NAMESPACE}/${IMAGE_NO_REPOSITORY} - # Push to the openshift registry - docker push ${REGISTRY}/${NAMESPACE}/${IMAGE_NO_REPOSITORY} -done diff --git a/go.mod b/go.mod new file mode 100644 index 00000000..46163aa3 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/uselagoon/lagoon-service-images + +go 1.22