Skip to content

Commit d948c21

Browse files
dtfranztmshort
authored andcommitted
Unpack Image (#811)
Builds and loads the unpacker binary into the operator-controller image so we don't need to use the rukpak image. Signed-off-by: dtfranz <[email protected]>
1 parent ee6ea6d commit d948c21

File tree

8 files changed

+180
-15
lines changed

8 files changed

+180
-15
lines changed

Dockerfile

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
11
# Note: This dockerfile does not build the binaries
22
# required and is intended to be built only with the
33
# 'make build' or 'make release' targets.
4+
# Stage 1:
5+
FROM gcr.io/distroless/static:debug-nonroot AS builder
6+
7+
# Stage 2:
48
FROM gcr.io/distroless/static:nonroot
59

10+
# Grab the cp binary so we can cp the unpack
11+
# binary to a shared volume in the bundle image
12+
COPY --from=builder /busybox/cp /cp
13+
614
WORKDIR /
715

816
COPY manager manager
17+
COPY unpack unpack
918

1019
EXPOSE 8080
1120

1221
USER 65532:65532
13-
14-
ENTRYPOINT ["/manager"]

Makefile

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -213,22 +213,24 @@ export GO_BUILD_LDFLAGS := -s -w -X $(shell go list -m)/version.Version=$(VERSIO
213213
export GO_BUILD_GCFLAGS := all=-trimpath=$(PWD)
214214
export GO_BUILD_FLAGS :=
215215

216-
BUILDCMD = go build $(GO_BUILD_FLAGS) -ldflags '$(GO_BUILD_LDFLAGS)' -gcflags '$(GO_BUILD_GCFLAGS)' -asmflags '$(GO_BUILD_ASMFLAGS)' -o $(BUILDBIN)/manager ./cmd/manager
216+
BINARIES=manager unpack
217+
218+
$(BINARIES):
219+
go build $(GO_BUILD_FLAGS) -tags '$(GO_BUILD_TAGS)' -ldflags '$(GO_BUILD_LDFLAGS)' -gcflags '$(GO_BUILD_GCFLAGS)' -asmflags '$(GO_BUILD_ASMFLAGS)' -o $(BUILDBIN)/$@ ./cmd/$@
217220

218221
.PHONY: build-deps
219222
build-deps: manifests generate fmt vet
220223

221224
.PHONY: build go-build-local
222225
build: build-deps go-build-local #HELP Build manager binary for current GOOS and GOARCH. Default target.
223226
go-build-local: BUILDBIN := bin
224-
go-build-local:
225-
$(BUILDCMD)
227+
go-build-local: $(BINARIES)
226228

227229
.PHONY: build-linux go-build-linux
228230
build-linux: build-deps go-build-linux #EXHELP Build manager binary for GOOS=linux and local GOARCH.
229231
go-build-linux: BUILDBIN := bin/linux
230-
go-build-linux:
231-
GOOS=linux $(BUILDCMD)
232+
go-build-linux: GOOS=linux
233+
go-build-linux: $(BINARIES)
232234

233235
.PHONY: run
234236
run: docker-build kind-cluster kind-load kind-deploy #HELP Build the operator-controller then deploy it into a new kind cluster.

cmd/manager/main.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ import (
4040
helmclient "github.com/operator-framework/helm-operator-plugins/pkg/client"
4141
"github.com/operator-framework/rukpak/pkg/source"
4242
"github.com/operator-framework/rukpak/pkg/storage"
43-
"github.com/operator-framework/rukpak/pkg/util"
4443

4544
"github.com/operator-framework/operator-controller/api/v1alpha1"
4645
"github.com/operator-framework/operator-controller/internal/catalogmetadata/cache"
@@ -53,9 +52,23 @@ import (
5352
)
5453

5554
var (
56-
setupLog = ctrl.Log.WithName("setup")
55+
setupLog = ctrl.Log.WithName("setup")
56+
defaultUnpackImage = "quay.io/operator-framework/operator-controller:latest"
57+
defaultSystemNamespace = "operator-controller-system"
5758
)
5859

60+
// podNamespace checks whether the controller is running in a Pod vs.
61+
// being run locally by inspecting the namespace file that gets mounted
62+
// automatically for Pods at runtime. If that file doesn't exist, then
63+
// return defaultSystemNamespace.
64+
func podNamespace() string {
65+
namespace, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
66+
if err != nil {
67+
return defaultSystemNamespace
68+
}
69+
return string(namespace)
70+
}
71+
5972
func main() {
6073
var (
6174
metricsAddr string
@@ -75,7 +88,7 @@ func main() {
7588
"Enabling this will ensure there is only one active controller manager.")
7689
flag.StringVar(&cachePath, "cache-path", "/var/cache", "The local directory path used for filesystem based caching")
7790
flag.StringVar(&systemNamespace, "system-namespace", "", "Configures the namespace that gets used to deploy system resources.")
78-
flag.StringVar(&unpackImage, "unpack-image", util.DefaultUnpackImage, "Configures the container image that gets used to unpack Bundle contents.")
91+
flag.StringVar(&unpackImage, "unpack-image", defaultUnpackImage, "Configures the container image that gets used to unpack Bundle contents.")
7992
flag.StringVar(&provisionerStorageDirectory, "provisioner-storage-dir", storage.DefaultBundleCacheDir, "The directory that is used to store bundle contents.")
8093
opts := zap.Options{
8194
Development: true,
@@ -89,7 +102,7 @@ func main() {
89102
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts), zap.StacktraceLevel(zapcore.DPanicLevel)))
90103

91104
if systemNamespace == "" {
92-
systemNamespace = util.PodNamespace()
105+
systemNamespace = podNamespace()
93106
}
94107

95108
dependentRequirement, err := k8slabels.NewRequirement(labels.OwnerKindKey, selection.In, []string{v1alpha1.ClusterExtensionKind})

cmd/unpack/main.go

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package main
2+
3+
import (
4+
"archive/tar"
5+
"bytes"
6+
"compress/gzip"
7+
"encoding/json"
8+
"fmt"
9+
"io"
10+
"io/fs"
11+
"log"
12+
"os"
13+
"path/filepath"
14+
15+
"github.com/spf13/cobra"
16+
"k8s.io/apimachinery/pkg/util/sets"
17+
)
18+
19+
func main() {
20+
var bundleDir string
21+
var opConVersion bool
22+
23+
skipRootPaths := sets.NewString(
24+
"/dev",
25+
"/etc",
26+
"/proc",
27+
"/product_name",
28+
"/product_uuid",
29+
"/sys",
30+
"/bin",
31+
)
32+
cmd := &cobra.Command{
33+
Use: "unpack",
34+
Args: cobra.ExactArgs(0),
35+
RunE: func(cmd *cobra.Command, _ []string) error {
36+
if opConVersion {
37+
// TODO
38+
//fmt.Println(version.String())
39+
os.Exit(0)
40+
}
41+
var err error
42+
bundleDir, err = filepath.Abs(bundleDir)
43+
if err != nil {
44+
log.Fatalf("get absolute path of bundle directory %q: %v", bundleDir, err)
45+
}
46+
47+
bundleFS := os.DirFS(bundleDir)
48+
buf := &bytes.Buffer{}
49+
gzw := gzip.NewWriter(buf)
50+
tw := tar.NewWriter(gzw)
51+
if err := fs.WalkDir(bundleFS, ".", func(path string, d fs.DirEntry, err error) error {
52+
if err != nil {
53+
return err
54+
}
55+
56+
if d.Type()&os.ModeSymlink != 0 {
57+
return nil
58+
}
59+
if bundleDir == "/" {
60+
// If bundleDir is the filesystem root, skip some known unrelated directories
61+
fullPath := filepath.Join(bundleDir, path)
62+
if skipRootPaths.Has(fullPath) {
63+
return filepath.SkipDir
64+
}
65+
}
66+
info, err := d.Info()
67+
if err != nil {
68+
return fmt.Errorf("get file info for %q: %v", path, err)
69+
}
70+
71+
h, err := tar.FileInfoHeader(info, "")
72+
if err != nil {
73+
return fmt.Errorf("build tar file info header for %q: %v", path, err)
74+
}
75+
h.Uid = 0
76+
h.Gid = 0
77+
h.Uname = ""
78+
h.Gname = ""
79+
h.Name = path
80+
81+
if err := tw.WriteHeader(h); err != nil {
82+
return fmt.Errorf("write tar header for %q: %v", path, err)
83+
}
84+
if d.IsDir() {
85+
return nil
86+
}
87+
f, err := bundleFS.Open(path)
88+
if err != nil {
89+
return fmt.Errorf("open file %q: %v", path, err)
90+
}
91+
if _, err := io.Copy(tw, f); err != nil {
92+
return fmt.Errorf("write tar data for %q: %v", path, err)
93+
}
94+
return nil
95+
}); err != nil {
96+
log.Fatalf("generate tar.gz for bundle dir %q: %v", bundleDir, err)
97+
}
98+
if err := tw.Close(); err != nil {
99+
log.Fatal(err)
100+
}
101+
if err := gzw.Close(); err != nil {
102+
log.Fatal(err)
103+
}
104+
105+
bundleMap := map[string]interface{}{
106+
"content": buf.Bytes(),
107+
}
108+
enc := json.NewEncoder(os.Stdout)
109+
if err := enc.Encode(bundleMap); err != nil {
110+
log.Fatalf("encode bundle map as JSON: %v", err)
111+
}
112+
return nil
113+
},
114+
}
115+
cmd.Flags().StringVar(&bundleDir, "bundle-dir", "", "directory in which the bundle can be found")
116+
cmd.Flags().BoolVar(&opConVersion, "version", false, "displays operator-controller version information")
117+
118+
if err := cmd.Execute(); err != nil {
119+
log.Fatal(err)
120+
}
121+
}

config/manager/kustomization.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,23 @@ images:
66
- name: controller
77
newName: quay.io/operator-framework/operator-controller
88
newTag: devel
9+
replacements:
10+
- source: # replaces UNPACK_IMAGE in manager.yaml with image set by kustomize above
11+
kind: Deployment
12+
group: apps
13+
version: v1
14+
name: controller-manager
15+
namespace: system
16+
fieldPath: spec.template.spec.containers.[name=manager].image
17+
targets:
18+
- select:
19+
kind: Deployment
20+
group: apps
21+
version: v1
22+
name: controller-manager
23+
namespace: system
24+
fieldPaths:
25+
- spec.template.spec.containers.[name=manager].args.0
26+
options:
27+
delimiter: "="
28+
index: 1

config/manager/manager.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ spec:
5252
- command:
5353
- /manager
5454
args:
55+
# The unpack-image arg must remain at index 0 for the kustomize replacement to work
56+
- "--unpack-image=UNPACK_IMAGE"
5557
- "--health-probe-bind-address=:8081"
5658
- "--metrics-bind-address=127.0.0.1:8080"
5759
- "--leader-elect"

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ require (
1212
github.com/operator-framework/catalogd v0.12.0
1313
github.com/operator-framework/helm-operator-plugins v0.2.1
1414
github.com/operator-framework/operator-registry v1.40.0
15-
github.com/operator-framework/rukpak v0.20.1-0.20240503190249-f2fc69ef9ff1
15+
github.com/operator-framework/rukpak v0.20.1-0.20240506151208-b6c74d40c3e9
16+
github.com/spf13/cobra v1.8.0
1617
github.com/spf13/pflag v1.0.5
1718
github.com/stretchr/testify v1.9.0
1819
github.com/vmware-tanzu/carvel-kapp-controller v0.51.0
@@ -165,7 +166,6 @@ require (
165166
github.com/sirupsen/logrus v1.9.3 // indirect
166167
github.com/skeema/knownhosts v1.2.2 // indirect
167168
github.com/spf13/cast v1.5.0 // indirect
168-
github.com/spf13/cobra v1.8.0 // indirect
169169
github.com/stoewer/go-strcase v1.3.0 // indirect
170170
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
171171
github.com/ulikunitz/xz v0.5.11 // indirect

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -404,8 +404,8 @@ github.com/operator-framework/operator-lib v0.12.0 h1:OzpMU5N7mvFgg/uje8FUUeD24A
404404
github.com/operator-framework/operator-lib v0.12.0/go.mod h1:ClpLUI7hctEF7F5DBe/kg041dq/4NLR7XC5tArY7bG4=
405405
github.com/operator-framework/operator-registry v1.40.0 h1:CaYNE4F/jzahpC7UCILItaIHmB5/oE0sS066nK+5Glw=
406406
github.com/operator-framework/operator-registry v1.40.0/go.mod h1:D2YxapkfRDgjqNTO9d3h3v0DeREbV+8utCLG52zrOy4=
407-
github.com/operator-framework/rukpak v0.20.1-0.20240503190249-f2fc69ef9ff1 h1:dB9owrQy5d/yjHuPNLw1dkudfWYLldJQBbmZ6pq+EAg=
408-
github.com/operator-framework/rukpak v0.20.1-0.20240503190249-f2fc69ef9ff1/go.mod h1:WAyS3DXZ19pLg/324PEoudWZmaRlYZ6i4j4NV3/T/mI=
407+
github.com/operator-framework/rukpak v0.20.1-0.20240506151208-b6c74d40c3e9 h1:itmEvkRAglIyVIFg7bmL+3G+HAYIrdK4ALEx7Ww1Nkc=
408+
github.com/operator-framework/rukpak v0.20.1-0.20240506151208-b6c74d40c3e9/go.mod h1:WAyS3DXZ19pLg/324PEoudWZmaRlYZ6i4j4NV3/T/mI=
409409
github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
410410
github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
411411
github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=

0 commit comments

Comments
 (0)