Skip to content

Commit

Permalink
fix lifecycle change summarizer to show relocated image
Browse files Browse the repository at this point in the history
fixes #187
  • Loading branch information
tomkennedy513 committed Aug 18, 2021
1 parent 4183b49 commit f775de8
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 116 deletions.
13 changes: 12 additions & 1 deletion pkg/commands/import/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/vmware-tanzu/kpack-cli/pkg/config"
importpkg "github.com/vmware-tanzu/kpack-cli/pkg/import"
"github.com/vmware-tanzu/kpack-cli/pkg/k8s"
"github.com/vmware-tanzu/kpack-cli/pkg/lifecycle"
"github.com/vmware-tanzu/kpack-cli/pkg/registry"
)

Expand Down Expand Up @@ -101,7 +102,17 @@ cat dependencies.yaml | kp import -f -`,

defaultKeychain := authn.DefaultKeychain
if showChanges {
hasChanges, summary, err := importpkg.SummarizeChange(ctx, defaultKeychain, descriptor, kpConfig, clusterstore.NewFactory(ch, imgRelocator, imgFetcher), clusterstack.NewFactory(ch, imgRelocator, imgFetcher), differ, cs)
hasChanges, summary, err := importpkg.SummarizeChange(
ctx,
defaultKeychain,
descriptor,
kpConfig,
clusterstore.NewFactory(ch, imgRelocator, imgFetcher),
clusterstack.NewFactory(ch, imgRelocator, imgFetcher),
lifecycle.NewFactory(imgRelocator, imgFetcher, cs.K8sClient),
differ,
cs,
)
if err != nil {
return err
}
Expand Down
16 changes: 7 additions & 9 deletions pkg/commands/lifecycle/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/spf13/cobra"

"github.com/vmware-tanzu/kpack-cli/pkg/commands"
"github.com/vmware-tanzu/kpack-cli/pkg/config"
"github.com/vmware-tanzu/kpack-cli/pkg/k8s"
"github.com/vmware-tanzu/kpack-cli/pkg/lifecycle"
"github.com/vmware-tanzu/kpack-cli/pkg/registry"
Expand Down Expand Up @@ -55,16 +56,13 @@ The canonical repository is read from the "canonical.repository" key of the "kp-
return err
}

cfg := lifecycle.ImageUpdaterConfig{
DryRun: ch.IsDryRun(),
IOWriter: ch.Writer(),
ImgFetcher: rup.Fetcher(tlsCfg),
ImgRelocator: rup.Relocator(ch.Writer(), tlsCfg, ch.CanChangeState()),
ClientSet: cs,
TLSConfig: tlsCfg,
}
factory := lifecycle.NewFactory(
rup.Relocator(ch.Writer(), tlsCfg, ch.CanChangeState()),
rup.Fetcher(tlsCfg),
cs.K8sClient)

configMap, err := lifecycle.UpdateImage(cmd.Context(), authn.DefaultKeychain, image, cfg)
ctx := cmd.Context()
configMap, err := factory.UpdateLifecycle(ctx, authn.DefaultKeychain, config.NewKpConfigProvider(cs).GetKpConfig(ctx), ch.IsDryRun(), image)
if err != nil {
return err
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/import/change_summarizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,18 @@ func SummarizeChange(
keychain authn.Keychain,
desc DependencyDescriptor,
kpConfig config.KpConfig,
storeFactory *clusterstore.Factory, stackFactory *clusterstack.Factory,
storeFactory *clusterstore.Factory, stackFactory *clusterstack.Factory, lifecycleRefGetter LifecycleRefGetter,
differ Differ, cs buildk8s.ClientSet) (hasChanges bool, changes string, err error) {

var summarizer changeSummarizer
iDiffer := &ImportDiffer{
Differ: differ,
StoreRefGetter: storeFactory,
StackRefGetter: stackFactory,
LifecycleRefGetter: lifecycleRefGetter,
}

err = writeLifecycleChange(ctx, desc.Lifecycle, iDiffer, cs, &summarizer)
err = writeLifecycleChange(ctx, keychain, kpConfig, desc.Lifecycle, iDiffer, cs, &summarizer)
if err != nil {
return
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/import/change_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ type changeWriter interface {
writeChange(header string)
}

func writeLifecycleChange(ctx context.Context, newLifecycle Lifecycle, differ *ImportDiffer, cs buildk8s.ClientSet, cw changeWriter) error {
func writeLifecycleChange(ctx context.Context, keychain authn.Keychain, kpConfig config.KpConfig, newLifecycle Lifecycle, differ *ImportDiffer, cs buildk8s.ClientSet, cw changeWriter) error {
if newLifecycle.Image != "" {
oldImg, err := lifecycle.GetImage(ctx, cs.K8sClient)
if err != nil {
return err
}

diff, err := differ.DiffLifecycle(oldImg, newLifecycle.Image)
diff, err := differ.DiffLifecycle(keychain, kpConfig, oldImg, newLifecycle.Image)
if err != nil {
return err
}
Expand Down
20 changes: 15 additions & 5 deletions pkg/import/import_differ.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,28 @@ type StackRefGetter interface {
RelocatedRunImage(authn.Keychain, config.KpConfig, string) (string, error)
}

type LifecycleRefGetter interface {
RelocatedLifecycleImage(authn.Keychain, config.KpConfig, string) (string, error)
}

type Differ interface {
Diff(dOld, dNew interface{}) (string, error)
}

type ImportDiffer struct {
Differ Differ
StoreRefGetter StoreRefGetter
StackRefGetter StackRefGetter
Differ Differ
StoreRefGetter StoreRefGetter
StackRefGetter StackRefGetter
LifecycleRefGetter LifecycleRefGetter
}

func (id *ImportDiffer) DiffLifecycle(oldImg string, newImg string) (string, error) {
return id.Differ.Diff(oldImg, newImg)
func (id *ImportDiffer) DiffLifecycle(keychain authn.Keychain, kpConfig config.KpConfig, oldImg string, newImg string) (string, error) {
relocatedLifecycle, err := id.LifecycleRefGetter.RelocatedLifecycleImage(keychain, kpConfig, newImg)
if err != nil {
return "", err
}

return id.Differ.Diff(oldImg, relocatedLifecycle)
}

func (id *ImportDiffer) DiffClusterStore(keychain authn.Keychain, kpConfig config.KpConfig, oldCS *v1alpha1.ClusterStore, newCS ClusterStore) (string, error) {
Expand Down
30 changes: 25 additions & 5 deletions pkg/import/import_differ_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/sclevine/spec"

"github.com/vmware-tanzu/kpack-cli/pkg/commands/fakes"
"github.com/vmware-tanzu/kpack-cli/pkg/config"
importpkg "github.com/vmware-tanzu/kpack-cli/pkg/import"

"github.com/sclevine/spec"

"github.com/vmware-tanzu/kpack-cli/pkg/commands"
)

Expand All @@ -44,14 +44,20 @@ func (rg *FakeRefGetter) RelocatedRunImage(keychain authn.Keychain, kpConfig con
return image, nil
}

func (rg *FakeRefGetter) RelocatedLifecycleImage(keychain authn.Keychain, kpConfig config.KpConfig, image string) (string, error) {
return image, nil
}

func testImportDiffer(t *testing.T, when spec.G, it spec.S) {
fakeDiffer := &fakes.FakeDiffer{DiffResult: "some-diff"}
fakeRefGetter := NewFakeRefGetter()
kpConfig := config.NewKpConfig("my-cool-repo", corev1.ObjectReference{})

importDiffer := importpkg.ImportDiffer{
Differ: fakeDiffer,
StoreRefGetter: fakeRefGetter,
StackRefGetter: fakeRefGetter,
Differ: fakeDiffer,
StoreRefGetter: fakeRefGetter,
StackRefGetter: fakeRefGetter,
LifecycleRefGetter: fakeRefGetter,
}
fakeKeychain := &registryfakes.FakeKeychain{}

Expand Down Expand Up @@ -203,4 +209,18 @@ func testImportDiffer(t *testing.T, when spec.G, it spec.S) {
require.Equal(t, nil, diffArg0)
})
})

when("DiffLifecycle", func() {
it("diffs lifecycle", func() {
oldLifecycle := "my-cool-repo/lifecycle@sha256:some-digest"
newLifecycle := "someregistry/lifecycle@sha256:some-new-digest"
diff, err := importDiffer.DiffLifecycle(fakeKeychain, kpConfig, oldLifecycle, newLifecycle)
require.NoError(t, err)
require.Equal(t, "some-diff", diff)

diffArg0, diffArg1 := fakeDiffer.Args()
require.Equal(t, oldLifecycle, diffArg0)
require.Equal(t, "my-cool-repo/lifecycle@sha256:some-new-digest", diffArg1)
})
})
}
123 changes: 123 additions & 0 deletions pkg/lifecycle/factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Copyright 2020-Present VMware, Inc.
// SPDX-License-Identifier: Apache-2.0

package lifecycle

import (
"context"
"fmt"
"path"

"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/v1"
"github.com/pivotal/kpack/pkg/registry/imagehelpers"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
k8s "k8s.io/client-go/kubernetes"

"github.com/vmware-tanzu/kpack-cli/pkg/config"
"github.com/vmware-tanzu/kpack-cli/pkg/registry"
)

const (
lifecycleImageName = "lifecycle"
lifecycleMetadataLabel = "io.buildpacks.lifecycle.metadata"
)

type PreUpdateHook func(*corev1.ConfigMap)

type Factory struct {
Relocator registry.Relocator
Fetcher registry.Fetcher
ClientSet k8s.Interface
}

func NewFactory(relocator registry.Relocator, fetcher registry.Fetcher, clientSet k8s.Interface) *Factory {
return &Factory{
Relocator: relocator,
Fetcher: fetcher,
ClientSet: clientSet,
}
}

func (f *Factory) UpdateLifecycle(ctx context.Context, keychain authn.Keychain, kpConfig config.KpConfig, dryRun bool, img string, hooks ...PreUpdateHook) (*corev1.ConfigMap, error) {
cm, err := getConfigMap(ctx, f.ClientSet)
if err != nil {
return cm, err
}

image, err := f.Fetcher.Fetch(keychain, img)
if err != nil {
return cm, err
}

if err = validateImage(image); err != nil {
return cm, err
}

relocatedImgTag, err := f.relocateLifecycleImage(keychain, kpConfig, image)
if err != nil {
return cm, err
}

cm.Data[lifecycleImageKey] = relocatedImgTag

for _, h := range hooks {
h(cm)
}

if !dryRun {
cm, err = updateConfigMap(ctx, cm, f.ClientSet)
}
return cm, err
}

func (f *Factory) relocateLifecycleImage(keychain authn.Keychain, kpConfig config.KpConfig, image v1.Image) (string, error) {
dstImgLocation, err := getLifecycleRef(kpConfig)
if err != nil {
return "", err
}

return f.Relocator.Relocate(keychain, image, dstImgLocation)
}

func (f *Factory) RelocatedLifecycleImage(keychain authn.Keychain, kpConfig config.KpConfig, img string) (string, error) {
image, err := f.Fetcher.Fetch(keychain, img)
if err != nil {
return "", err
}

digest, err := image.Digest()
if err != nil {
return "", err
}

relocatedLifecyclePath, err := getLifecycleRef(kpConfig)
if err != nil {
return "", err
}

return fmt.Sprintf("%s@%s", relocatedLifecyclePath, digest.String()), nil
}

func getLifecycleRef(kpConfig config.KpConfig) (string, error) {
canonicalRepo, err := kpConfig.CanonicalRepository()
if err != nil {
return "", err
}

dstImgLocation := path.Join(canonicalRepo, lifecycleImageName)
return dstImgLocation, nil
}

func validateImage(img v1.Image) error {
hasLabel, err := imagehelpers.HasLabel(img, lifecycleMetadataLabel)
if err != nil {
return err
}

if !hasLabel {
return errors.New("image missing lifecycle metadata")
}
return nil
}
Loading

0 comments on commit f775de8

Please sign in to comment.