Skip to content

Commit 16bf815

Browse files
dtfranzbentito
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 4e97b7a commit 16bf815

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
@@ -217,22 +217,24 @@ export GO_BUILD_FLAGS :=
217217
export GO_BUILD_LDFLAGS := -s -w \
218218
-X '$(VERSION_PATH).version=$(VERSION)' \
219219

220-
BUILDCMD = go build $(GO_BUILD_FLAGS) -ldflags '$(GO_BUILD_LDFLAGS)' -gcflags '$(GO_BUILD_GCFLAGS)' -asmflags '$(GO_BUILD_ASMFLAGS)' -o $(BUILDBIN)/manager ./cmd/manager
220+
BINARIES=manager unpack
221+
222+
$(BINARIES):
223+
go build $(GO_BUILD_FLAGS) -tags '$(GO_BUILD_TAGS)' -ldflags '$(GO_BUILD_LDFLAGS)' -gcflags '$(GO_BUILD_GCFLAGS)' -asmflags '$(GO_BUILD_ASMFLAGS)' -o $(BUILDBIN)/$@ ./cmd/$@
221224

222225
.PHONY: build-deps
223226
build-deps: manifests generate fmt vet
224227

225228
.PHONY: build go-build-local
226229
build: build-deps go-build-local #HELP Build manager binary for current GOOS and GOARCH. Default target.
227230
go-build-local: BUILDBIN := bin
228-
go-build-local:
229-
$(BUILDCMD)
231+
go-build-local: $(BINARIES)
230232

231233
.PHONY: build-linux go-build-linux
232234
build-linux: build-deps go-build-linux #EXHELP Build manager binary for GOOS=linux and local GOARCH.
233235
go-build-linux: BUILDBIN := bin/linux
234-
go-build-linux:
235-
GOOS=linux $(BUILDCMD)
236+
go-build-linux: GOOS=linux
237+
go-build-linux: $(BINARIES)
236238

237239
.PHONY: run
238240
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"
@@ -54,9 +53,23 @@ import (
5453
)
5554

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

61+
// podNamespace checks whether the controller is running in a Pod vs.
62+
// being run locally by inspecting the namespace file that gets mounted
63+
// automatically for Pods at runtime. If that file doesn't exist, then
64+
// return defaultSystemNamespace.
65+
func podNamespace() string {
66+
namespace, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
67+
if err != nil {
68+
return defaultSystemNamespace
69+
}
70+
return string(namespace)
71+
}
72+
6073
func main() {
6174
var (
6275
metricsAddr string
@@ -78,7 +91,7 @@ func main() {
7891
flag.StringVar(&cachePath, "cache-path", "/var/cache", "The local directory path used for filesystem based caching")
7992
flag.BoolVar(&operatorControllerVersion, "version", false, "Prints operator-controller version information")
8093
flag.StringVar(&systemNamespace, "system-namespace", "", "Configures the namespace that gets used to deploy system resources.")
81-
flag.StringVar(&unpackImage, "unpack-image", util.DefaultUnpackImage, "Configures the container image that gets used to unpack Bundle contents.")
94+
flag.StringVar(&unpackImage, "unpack-image", defaultUnpackImage, "Configures the container image that gets used to unpack Bundle contents.")
8295
flag.StringVar(&provisionerStorageDirectory, "provisioner-storage-dir", storage.DefaultBundleCacheDir, "The directory that is used to store bundle contents.")
8396
opts := zap.Options{
8497
Development: true,
@@ -98,7 +111,7 @@ func main() {
98111
setupLog.Info("starting up the controller", "version info", version.String())
99112

100113
if systemNamespace == "" {
101-
systemNamespace = util.PodNamespace()
114+
systemNamespace = podNamespace()
102115
}
103116

104117
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
go.uber.org/zap v1.27.0
@@ -150,7 +151,6 @@ require (
150151
github.com/sirupsen/logrus v1.9.3 // indirect
151152
github.com/skeema/knownhosts v1.2.2 // indirect
152153
github.com/spf13/cast v1.5.0 // indirect
153-
github.com/spf13/cobra v1.8.0 // indirect
154154
github.com/stoewer/go-strcase v1.3.0 // indirect
155155
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
156156
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)