Skip to content

Commit

Permalink
Unpack Image
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 committed May 3, 2024
1 parent 8afcb15 commit f5c15bd
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 9 deletions.
3 changes: 1 addition & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ FROM gcr.io/distroless/static:nonroot
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 @@ -203,22 +203,24 @@ export GO_BUILD_GCFLAGS ?= all=-trimpath=${PWD}
export GO_BUILD_TAGS ?= upstream
export GO_BUILD_FLAGS ?=

BUILDCMD = go build $(GO_BUILD_FLAGS) -tags '$(GO_BUILD_TAGS)' -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
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
5 changes: 4 additions & 1 deletion internal/rukpak/source/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ func (i *Image) ensureUnpackPod(ctx context.Context, bs *rukpakapi.BundleSource,
}

func (i *Image) getDesiredPodApplyConfig(bs *rukpakapi.BundleSource, ce *clusterextension.ClusterExtension) *applyconfigurationcorev1.PodApplyConfiguration {
// TODO (dfranz): Not sure if below comment still applies? We are now running
// in restricted namespace as non-root, so we shouldn't run into problems.

// TODO (tyslaton): Address unpacker pod allowing root users for image sources
//
// In our current implementation, we are creating a pod that uses the image
Expand Down Expand Up @@ -159,7 +162,7 @@ func (i *Image) getDesiredPodApplyConfig(bs *rukpakapi.BundleSource, ce *cluster
WithEmptyDir(applyconfigurationcorev1.EmptyDirVolumeSource()),
).
WithSecurityContext(applyconfigurationcorev1.PodSecurityContext().
WithRunAsNonRoot(false).
WithRunAsNonRoot(true).
WithSeccompProfile(applyconfigurationcorev1.SeccompProfile().
WithType(corev1.SeccompProfileTypeRuntimeDefault),
),
Expand Down
2 changes: 1 addition & 1 deletion internal/rukpak/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
// TODO verify these
const (
DefaultSystemNamespace = "operator-controller-system"
DefaultUnpackImage = "quay.io/operator-framework/rukpak:main"
DefaultUnpackImage = "quay.io/operator-framework/operator-controller:latest"
)

func MergeMaps(maps ...map[string]string) map[string]string {
Expand Down

0 comments on commit f5c15bd

Please sign in to comment.