Skip to content

Commit

Permalink
Unpack Image (#811)
Browse files Browse the repository at this point in the history
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 <dfranz@redhat.com>
  • Loading branch information
dtfranz authored and bentito committed May 14, 2024
1 parent 4e97b7a commit 16bf815
Show file tree
Hide file tree
Showing 8 changed files with 180 additions and 15 deletions.
11 changes: 9 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
# Note: This dockerfile does not build the binaries
# required and is intended to be built only with the
# 'make build' or 'make release' targets.
# Stage 1:
FROM gcr.io/distroless/static:debug-nonroot AS builder

# Stage 2:
FROM gcr.io/distroless/static:nonroot

# Grab the cp binary so we can cp the unpack
# binary to a shared volume in the bundle image
COPY --from=builder /busybox/cp /cp

WORKDIR /

COPY manager manager
COPY unpack unpack

EXPOSE 8080

USER 65532:65532

ENTRYPOINT ["/manager"]
12 changes: 7 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -217,22 +217,24 @@ export GO_BUILD_FLAGS :=
export GO_BUILD_LDFLAGS := -s -w \
-X '$(VERSION_PATH).version=$(VERSION)' \

BUILDCMD = go build $(GO_BUILD_FLAGS) -ldflags '$(GO_BUILD_LDFLAGS)' -gcflags '$(GO_BUILD_GCFLAGS)' -asmflags '$(GO_BUILD_ASMFLAGS)' -o $(BUILDBIN)/manager ./cmd/manager
BINARIES=manager unpack

$(BINARIES):
go build $(GO_BUILD_FLAGS) -tags '$(GO_BUILD_TAGS)' -ldflags '$(GO_BUILD_LDFLAGS)' -gcflags '$(GO_BUILD_GCFLAGS)' -asmflags '$(GO_BUILD_ASMFLAGS)' -o $(BUILDBIN)/$@ ./cmd/$@

.PHONY: build-deps
build-deps: manifests generate fmt vet

.PHONY: build go-build-local
build: build-deps go-build-local #HELP Build manager binary for current GOOS and GOARCH. Default target.
go-build-local: BUILDBIN := bin
go-build-local:
$(BUILDCMD)
go-build-local: $(BINARIES)

.PHONY: build-linux go-build-linux
build-linux: build-deps go-build-linux #EXHELP Build manager binary for GOOS=linux and local GOARCH.
go-build-linux: BUILDBIN := bin/linux
go-build-linux:
GOOS=linux $(BUILDCMD)
go-build-linux: GOOS=linux
go-build-linux: $(BINARIES)

.PHONY: run
run: docker-build kind-cluster kind-load kind-deploy #HELP Build the operator-controller then deploy it into a new kind cluster.
Expand Down
21 changes: 17 additions & 4 deletions cmd/manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import (
helmclient "github.com/operator-framework/helm-operator-plugins/pkg/client"
"github.com/operator-framework/rukpak/pkg/source"
"github.com/operator-framework/rukpak/pkg/storage"
"github.com/operator-framework/rukpak/pkg/util"

"github.com/operator-framework/operator-controller/api/v1alpha1"
"github.com/operator-framework/operator-controller/internal/catalogmetadata/cache"
Expand All @@ -54,9 +53,23 @@ import (
)

var (
setupLog = ctrl.Log.WithName("setup")
setupLog = ctrl.Log.WithName("setup")
defaultUnpackImage = "quay.io/operator-framework/operator-controller:latest"
defaultSystemNamespace = "operator-controller-system"
)

// podNamespace checks whether the controller is running in a Pod vs.
// being run locally by inspecting the namespace file that gets mounted
// automatically for Pods at runtime. If that file doesn't exist, then
// return defaultSystemNamespace.
func podNamespace() string {
namespace, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
if err != nil {
return defaultSystemNamespace
}
return string(namespace)
}

func main() {
var (
metricsAddr string
Expand All @@ -78,7 +91,7 @@ func main() {
flag.StringVar(&cachePath, "cache-path", "/var/cache", "The local directory path used for filesystem based caching")
flag.BoolVar(&operatorControllerVersion, "version", false, "Prints operator-controller version information")
flag.StringVar(&systemNamespace, "system-namespace", "", "Configures the namespace that gets used to deploy system resources.")
flag.StringVar(&unpackImage, "unpack-image", util.DefaultUnpackImage, "Configures the container image that gets used to unpack Bundle contents.")
flag.StringVar(&unpackImage, "unpack-image", defaultUnpackImage, "Configures the container image that gets used to unpack Bundle contents.")
flag.StringVar(&provisionerStorageDirectory, "provisioner-storage-dir", storage.DefaultBundleCacheDir, "The directory that is used to store bundle contents.")
opts := zap.Options{
Development: true,
Expand All @@ -98,7 +111,7 @@ func main() {
setupLog.Info("starting up the controller", "version info", version.String())

if systemNamespace == "" {
systemNamespace = util.PodNamespace()
systemNamespace = podNamespace()
}

dependentRequirement, err := k8slabels.NewRequirement(labels.OwnerKindKey, selection.In, []string{v1alpha1.ClusterExtensionKind})
Expand Down
121 changes: 121 additions & 0 deletions cmd/unpack/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package main

import (
"archive/tar"
"bytes"
"compress/gzip"
"encoding/json"
"fmt"
"io"
"io/fs"
"log"
"os"
"path/filepath"

"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/util/sets"
)

func main() {
var bundleDir string
var opConVersion bool

skipRootPaths := sets.NewString(
"/dev",
"/etc",
"/proc",
"/product_name",
"/product_uuid",
"/sys",
"/bin",
)
cmd := &cobra.Command{
Use: "unpack",
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, _ []string) error {
if opConVersion {
// TODO
//fmt.Println(version.String())
os.Exit(0)
}
var err error
bundleDir, err = filepath.Abs(bundleDir)
if err != nil {
log.Fatalf("get absolute path of bundle directory %q: %v", bundleDir, err)
}

bundleFS := os.DirFS(bundleDir)
buf := &bytes.Buffer{}
gzw := gzip.NewWriter(buf)
tw := tar.NewWriter(gzw)
if err := fs.WalkDir(bundleFS, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}

if d.Type()&os.ModeSymlink != 0 {
return nil
}
if bundleDir == "/" {
// If bundleDir is the filesystem root, skip some known unrelated directories
fullPath := filepath.Join(bundleDir, path)
if skipRootPaths.Has(fullPath) {
return filepath.SkipDir
}
}
info, err := d.Info()
if err != nil {
return fmt.Errorf("get file info for %q: %v", path, err)
}

h, err := tar.FileInfoHeader(info, "")
if err != nil {
return fmt.Errorf("build tar file info header for %q: %v", path, err)
}
h.Uid = 0
h.Gid = 0
h.Uname = ""
h.Gname = ""
h.Name = path

if err := tw.WriteHeader(h); err != nil {
return fmt.Errorf("write tar header for %q: %v", path, err)
}
if d.IsDir() {
return nil
}
f, err := bundleFS.Open(path)
if err != nil {
return fmt.Errorf("open file %q: %v", path, err)
}
if _, err := io.Copy(tw, f); err != nil {
return fmt.Errorf("write tar data for %q: %v", path, err)
}
return nil
}); err != nil {
log.Fatalf("generate tar.gz for bundle dir %q: %v", bundleDir, err)
}
if err := tw.Close(); err != nil {
log.Fatal(err)
}
if err := gzw.Close(); err != nil {
log.Fatal(err)
}

bundleMap := map[string]interface{}{
"content": buf.Bytes(),
}
enc := json.NewEncoder(os.Stdout)
if err := enc.Encode(bundleMap); err != nil {
log.Fatalf("encode bundle map as JSON: %v", err)
}
return nil
},
}
cmd.Flags().StringVar(&bundleDir, "bundle-dir", "", "directory in which the bundle can be found")
cmd.Flags().BoolVar(&opConVersion, "version", false, "displays operator-controller version information")

if err := cmd.Execute(); err != nil {
log.Fatal(err)
}
}
20 changes: 20 additions & 0 deletions config/manager/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,23 @@ images:
- name: controller
newName: quay.io/operator-framework/operator-controller
newTag: devel
replacements:
- source: # replaces UNPACK_IMAGE in manager.yaml with image set by kustomize above
kind: Deployment
group: apps
version: v1
name: controller-manager
namespace: system
fieldPath: spec.template.spec.containers.[name=manager].image
targets:
- select:
kind: Deployment
group: apps
version: v1
name: controller-manager
namespace: system
fieldPaths:
- spec.template.spec.containers.[name=manager].args.0
options:
delimiter: "="
index: 1
2 changes: 2 additions & 0 deletions config/manager/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ spec:
- command:
- /manager
args:
# The unpack-image arg must remain at index 0 for the kustomize replacement to work
- "--unpack-image=UNPACK_IMAGE"
- "--health-probe-bind-address=:8081"
- "--metrics-bind-address=127.0.0.1:8080"
- "--leader-elect"
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ require (
github.com/operator-framework/catalogd v0.12.0
github.com/operator-framework/helm-operator-plugins v0.2.1
github.com/operator-framework/operator-registry v1.40.0
github.com/operator-framework/rukpak v0.20.1-0.20240503190249-f2fc69ef9ff1
github.com/operator-framework/rukpak v0.20.1-0.20240506151208-b6c74d40c3e9
github.com/spf13/cobra v1.8.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.9.0
go.uber.org/zap v1.27.0
Expand Down Expand Up @@ -150,7 +151,6 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/skeema/knownhosts v1.2.2 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/cobra v1.8.0 // indirect
github.com/stoewer/go-strcase v1.3.0 // indirect
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
github.com/ulikunitz/xz v0.5.11 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -404,8 +404,8 @@ github.com/operator-framework/operator-lib v0.12.0 h1:OzpMU5N7mvFgg/uje8FUUeD24A
github.com/operator-framework/operator-lib v0.12.0/go.mod h1:ClpLUI7hctEF7F5DBe/kg041dq/4NLR7XC5tArY7bG4=
github.com/operator-framework/operator-registry v1.40.0 h1:CaYNE4F/jzahpC7UCILItaIHmB5/oE0sS066nK+5Glw=
github.com/operator-framework/operator-registry v1.40.0/go.mod h1:D2YxapkfRDgjqNTO9d3h3v0DeREbV+8utCLG52zrOy4=
github.com/operator-framework/rukpak v0.20.1-0.20240503190249-f2fc69ef9ff1 h1:dB9owrQy5d/yjHuPNLw1dkudfWYLldJQBbmZ6pq+EAg=
github.com/operator-framework/rukpak v0.20.1-0.20240503190249-f2fc69ef9ff1/go.mod h1:WAyS3DXZ19pLg/324PEoudWZmaRlYZ6i4j4NV3/T/mI=
github.com/operator-framework/rukpak v0.20.1-0.20240506151208-b6c74d40c3e9 h1:itmEvkRAglIyVIFg7bmL+3G+HAYIrdK4ALEx7Ww1Nkc=
github.com/operator-framework/rukpak v0.20.1-0.20240506151208-b6c74d40c3e9/go.mod h1:WAyS3DXZ19pLg/324PEoudWZmaRlYZ6i4j4NV3/T/mI=
github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=
Expand Down

0 comments on commit 16bf815

Please sign in to comment.