Skip to content

Commit

Permalink
Merge pull request #235 from cert-manager/self-upgrade
Browse files Browse the repository at this point in the history
[CI] Merge self-upgrade into main
  • Loading branch information
cert-manager-prow[bot] authored Apr 19, 2024
2 parents d3abffc + 495d76b commit a2642a1
Show file tree
Hide file tree
Showing 10 changed files with 428 additions and 286 deletions.
26 changes: 13 additions & 13 deletions klone.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,65 +10,65 @@ targets:
- folder_name: boilerplate
repo_url: https://github.com/cert-manager/makefile-modules.git
repo_ref: main
repo_hash: 9f5f978d28e4c4b4938d5f6257338eb922524318
repo_hash: fa9c9274d1d852de501461b9442f7206aaf74007
repo_path: modules/boilerplate
- folder_name: cert-manager
repo_url: https://github.com/cert-manager/makefile-modules.git
repo_ref: main
repo_hash: 9f5f978d28e4c4b4938d5f6257338eb922524318
repo_hash: fa9c9274d1d852de501461b9442f7206aaf74007
repo_path: modules/cert-manager
- folder_name: controller-gen
repo_url: https://github.com/cert-manager/makefile-modules.git
repo_ref: main
repo_hash: 9f5f978d28e4c4b4938d5f6257338eb922524318
repo_hash: fa9c9274d1d852de501461b9442f7206aaf74007
repo_path: modules/controller-gen
- folder_name: generate-verify
repo_url: https://github.com/cert-manager/makefile-modules.git
repo_ref: main
repo_hash: 9f5f978d28e4c4b4938d5f6257338eb922524318
repo_hash: fa9c9274d1d852de501461b9442f7206aaf74007
repo_path: modules/generate-verify
- folder_name: go
repo_url: https://github.com/cert-manager/makefile-modules.git
repo_ref: main
repo_hash: 9f5f978d28e4c4b4938d5f6257338eb922524318
repo_hash: fa9c9274d1d852de501461b9442f7206aaf74007
repo_path: modules/go
- folder_name: helm
repo_url: https://github.com/cert-manager/makefile-modules.git
repo_ref: main
repo_hash: 9f5f978d28e4c4b4938d5f6257338eb922524318
repo_hash: fa9c9274d1d852de501461b9442f7206aaf74007
repo_path: modules/helm
- folder_name: help
repo_url: https://github.com/cert-manager/makefile-modules.git
repo_ref: main
repo_hash: 9f5f978d28e4c4b4938d5f6257338eb922524318
repo_hash: fa9c9274d1d852de501461b9442f7206aaf74007
repo_path: modules/help
- folder_name: kind
repo_url: https://github.com/cert-manager/makefile-modules.git
repo_ref: main
repo_hash: 9f5f978d28e4c4b4938d5f6257338eb922524318
repo_hash: fa9c9274d1d852de501461b9442f7206aaf74007
repo_path: modules/kind
- folder_name: klone
repo_url: https://github.com/cert-manager/makefile-modules.git
repo_ref: main
repo_hash: 9f5f978d28e4c4b4938d5f6257338eb922524318
repo_hash: fa9c9274d1d852de501461b9442f7206aaf74007
repo_path: modules/klone
- folder_name: oci-build
repo_url: https://github.com/cert-manager/makefile-modules.git
repo_ref: main
repo_hash: 9f5f978d28e4c4b4938d5f6257338eb922524318
repo_hash: fa9c9274d1d852de501461b9442f7206aaf74007
repo_path: modules/oci-build
- folder_name: oci-publish
repo_url: https://github.com/cert-manager/makefile-modules.git
repo_ref: main
repo_hash: 9f5f978d28e4c4b4938d5f6257338eb922524318
repo_hash: fa9c9274d1d852de501461b9442f7206aaf74007
repo_path: modules/oci-publish
- folder_name: repository-base
repo_url: https://github.com/cert-manager/makefile-modules.git
repo_ref: main
repo_hash: 9f5f978d28e4c4b4938d5f6257338eb922524318
repo_hash: fa9c9274d1d852de501461b9442f7206aaf74007
repo_path: modules/repository-base
- folder_name: tools
repo_url: https://github.com/cert-manager/makefile-modules.git
repo_ref: main
repo_hash: 9f5f978d28e4c4b4938d5f6257338eb922524318
repo_hash: fa9c9274d1d852de501461b9442f7206aaf74007
repo_path: modules/tools
1 change: 1 addition & 0 deletions make/_shared/oci-build/00_mod.mk
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ GOEXPERIMENT ?= # empty by default
define default_per_build_variables
cgo_enabled_$1 ?= $(CGO_ENABLED)
goexperiment_$1 ?= $(GOEXPERIMENT)
oci_additional_layers_$1 ?=
endef

$(foreach build_name,$(build_names),$(eval $(call default_per_build_variables,$(build_name))))
Expand Down
4 changes: 4 additions & 0 deletions make/_shared/oci-build/01_mod.mk
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ $(oci_build_targets): oci-build-%: ko-config-% | $(NEEDS_KO) $(NEEDS_GO) $(NEEDS
--push=false \
--bare

$(IMAGE_TOOL) append-layers \
$(CURDIR)/$(oci_layout_path_$*) \
$(oci_additional_layers_$*)

$(IMAGE_TOOL) list-digests \
$(CURDIR)/$(oci_layout_path_$*) \
> $(oci_digest_path_$*)
Expand Down
180 changes: 180 additions & 0 deletions make/_shared/oci-build/image_tool/append_layers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
/*
Copyright 2023 The cert-manager Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
"archive/tar"
"bytes"
"io"
"io/fs"
"log/slog"
"os"
"path/filepath"

v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/layout"
"github.com/google/go-containerregistry/pkg/v1/match"
"github.com/google/go-containerregistry/pkg/v1/mutate"
"github.com/google/go-containerregistry/pkg/v1/tarball"
"github.com/spf13/cobra"
)

var CommandAppendLayers = cobra.Command{
Use: "append-layers oci-path [path-to-tarball...]",
Short: "Appends a tarball or directory to every image in an OCI index.",
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
oci := args[0]
extra := args[1:]

if len(extra) == 0 {
return
}

layers := []v1.Layer{}
for _, path := range extra {
layers = append(layers, loadLayerFromDirOrTarball(path))
}

appendLayersToAllImages(oci, layers...)
},
}

func loadLayerFromDirOrTarball(path string) v1.Layer {
stat, err := os.Stat(path)
must("could not open directory or tarball", err)

var layer v1.Layer
if stat.IsDir() {
var buf bytes.Buffer

tw := tar.NewWriter(&buf)

filepath.Walk(path, func(target string, info fs.FileInfo, err error) error {
must("walk error", err)

header, err := tar.FileInfoHeader(info, info.Name())
must("could not create tar header", err)

name, err := filepath.Rel(path, target)
must("could not build relative path", err)

// Write simplified header, this removes all fields that would cause
// the build to be non-reproducible (like modtime for example)
err = tw.WriteHeader(&tar.Header{
Typeflag: header.Typeflag,
Name: name,
Mode: header.Mode,
Linkname: header.Linkname,
Size: header.Size,
})

must("could not write tar header", err)

if !info.IsDir() {
file, err := os.Open(target)
must("could not write tar contents", err)

defer file.Close()

_, err = io.Copy(tw, file)
must("could not write tar contents", err)
}

return nil
})

tw.Close()

byts := buf.Bytes()

layer, err = tarball.LayerFromOpener(func() (io.ReadCloser, error) {
return io.NopCloser(bytes.NewReader(byts)), nil
})

} else {
layer, err = tarball.LayerFromFile(path)
}

must("could not open directory or tarball", err)
return layer
}

func appendLayersToAllImages(oci string, layers ...v1.Layer) {
path, err := layout.FromPath(oci)
must("could not load oci directory", err)

index, err := path.ImageIndex()
must("could not load oci image index", err)

index = appendLayersToImageIndex(index, layers)

_, err = layout.Write(oci, index)
must("could not write image", err)
}

func appendLayersToImageIndex(index v1.ImageIndex, layers []v1.Layer) v1.ImageIndex {
manifest, err := index.IndexManifest()
must("could not load oci image manifest", err)

for _, descriptor := range manifest.Manifests {
switch {
case descriptor.MediaType.IsImage():
slog.Info("found image", "digest", descriptor.Digest, "platform", descriptor.Platform)

img, err := index.Image(descriptor.Digest)
must("could not load oci image with digest", err)

img, err = mutate.AppendLayers(img, layers...)
must("could not load append layer to image", err)

digest, err := img.Digest()
must("could not get image digest", err)

slog.Info("appended layers to image", "old_digest", descriptor.Digest, "digest", digest, "platform", descriptor.Platform)

index = mutate.RemoveManifests(index, match.Digests(descriptor.Digest))

descriptor.Digest = digest
index = mutate.AppendManifests(index, mutate.IndexAddendum{
Add: img,
Descriptor: descriptor,
})

case descriptor.MediaType.IsIndex():
slog.Info("found image index", "digest", descriptor.Digest)

child, err := index.ImageIndex(descriptor.Digest)
must("could not load oci image manifest", err)

child = appendLayersToImageIndex(child, layers)

digest, err := child.Digest()
must("could not get image digest", err)

index = mutate.RemoveManifests(index, match.Digests(descriptor.Digest))

descriptor.Digest = digest
index = mutate.AppendManifests(index, mutate.IndexAddendum{
Add: child,
Descriptor: descriptor,
})
}
}

return index
}
97 changes: 97 additions & 0 deletions make/_shared/oci-build/image_tool/convert_to_docker_tar.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
Copyright 2023 The cert-manager Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
"runtime"

"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/layout"
"github.com/google/go-containerregistry/pkg/v1/match"
"github.com/google/go-containerregistry/pkg/v1/tarball"
"github.com/spf13/cobra"
)

var CommandConvertToDockerTar = cobra.Command{
Use: "convert-to-docker-tar oci-path output image-name",
Short: "Reads the OCI directory and outputs a tarball that is compatible with \"docker load\"",
Args: cobra.ExactArgs(3),
Run: func(cmd *cobra.Command, args []string) {
path := args[0]
output := args[1]
imageName := args[2]

ociLayout, err := layout.FromPath(path)
must("could not load oci directory", err)

index, err := ociLayout.ImageIndex()
must("could not load oci image index", err)

images := getImagesFromIndex(index, func(desc v1.Descriptor) bool {
return desc.Platform != nil && desc.Platform.Architecture == runtime.GOARCH
})

switch {
case len(images) == 0:
fail("no matching images found")
case len(images) > 1:
fail("multiple matching images found")
}

ref, err := name.ParseReference(imageName)
must("invalid image name", err)

err = tarball.WriteToFile(output, ref, images[0])
must("could not write tarball", err)
},
}

func getImagesFromIndex(index v1.ImageIndex, matcher match.Matcher) (images []v1.Image) {
manifest, err := index.IndexManifest()
must("could not load oci index manifest", err)

for _, descriptor := range manifest.Manifests {
switch {
case descriptor.MediaType.IsImage():
// If the platform is not part of the index manifest, attempt to
// load it from the image config
if descriptor.Platform == nil {
img, err := index.Image(descriptor.Digest)
must("could not load image", err)

cfg, err := img.ConfigFile()
must("could not load image config", err)

descriptor.Platform = cfg.Platform()
}

if matcher(descriptor) {
img, err := index.Image(descriptor.Digest)
must("could not load image", err)
images = append(images, img)
}

case descriptor.MediaType.IsIndex():
idx, err := index.ImageIndex(descriptor.Digest)
must("could not load image index", err)
images = append(images, getImagesFromIndex(idx, matcher)...)
}
}

return
}
Loading

0 comments on commit a2642a1

Please sign in to comment.