Skip to content

Commit

Permalink
Merge pull request #995 from carolynvs/force-all-tags
Browse files Browse the repository at this point in the history
Add --force flag to commands that pull tags
  • Loading branch information
carolynvs-msft authored Apr 16, 2020
2 parents 48d5f0c + b2ef6b5 commit 772ffb2
Show file tree
Hide file tree
Showing 17 changed files with 172 additions and 11 deletions.
3 changes: 3 additions & 0 deletions cmd/porter/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,5 +347,8 @@ func buildBundleArchiveCommand(p *porter.Porter) *cobra.Command {
f.StringVar(&opts.CNABFile, "cnab-file", "", "Path to the CNAB bundle.json file.")
f.StringVarP(&opts.Tag, "tag", "t", "",
"Use a bundle in an OCI registry specified by the given tag")
f.BoolVar(&opts.Force, "force", false,
"Force a fresh pull of the bundle")

return &cmd
}
3 changes: 3 additions & 0 deletions cmd/porter/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ will then provide it to the bundle in the correct location. `,
"Generate credential but do not save it.")
f.StringVar(&opts.Tag, "tag", "",
"Use a bundle in an OCI registry specified by the given tag.")
f.BoolVar(&opts.Force, "force", false,
"Force a fresh pull of the bundle")

return cmd
}

Expand Down
2 changes: 2 additions & 0 deletions cmd/porter/explain.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ func buildBundleExplainCommand(p *porter.Porter) *cobra.Command {
f.StringVar(&opts.CNABFile, "cnab-file", "", "Path to the CNAB bundle.json file.")
f.StringVarP(&opts.Tag, "tag", "t", "",
"Use a bundle in an OCI registry specified by the given tag")
f.BoolVar(&opts.Force, "force", false,
"Force a fresh pull of the bundle")
f.StringVarP(&opts.RawFormat, "output", "o", "table",
"Specify an output format. Allowed values: table, json, yaml")
return &cmd
Expand Down
2 changes: 2 additions & 0 deletions cmd/porter/inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ like parameters, credentials, outputs and custom actions available.
f.StringVar(&opts.CNABFile, "cnab-file", "", "Path to the CNAB bundle.json file.")
f.StringVarP(&opts.Tag, "tag", "t", "",
"Use a bundle in an OCI registry specified by the given tag")
f.BoolVar(&opts.Force, "force", false,
"Force a fresh pull of the bundle")
f.StringVarP(&opts.RawFormat, "output", "o", "table",
"Specify an output format. Allowed values: table, json, yaml")
return &cmd
Expand Down
1 change: 1 addition & 0 deletions docs/content/cli/archive.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ porter archive [flags]
```
--cnab-file string Path to the CNAB bundle.json file.
-f, --file porter.yaml Path to the Porter manifest. Defaults to porter.yaml in the current directory.
--force Force a fresh pull of the bundle
-h, --help help for archive
-t, --tag string Use a bundle in an OCI registry specified by the given tag
```
Expand Down
1 change: 1 addition & 0 deletions docs/content/cli/bundles_archive.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ porter bundles archive [flags]
```
--cnab-file string Path to the CNAB bundle.json file.
-f, --file porter.yaml Path to the Porter manifest. Defaults to porter.yaml in the current directory.
--force Force a fresh pull of the bundle
-h, --help help for archive
-t, --tag string Use a bundle in an OCI registry specified by the given tag
```
Expand Down
1 change: 1 addition & 0 deletions docs/content/cli/bundles_explain.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ porter bundles explain [flags]
```
--cnab-file string Path to the CNAB bundle.json file.
-f, --file porter.yaml Path to the Porter manifest. Defaults to porter.yaml in the current directory.
--force Force a fresh pull of the bundle
-h, --help help for explain
-o, --output string Specify an output format. Allowed values: table, json, yaml (default "table")
-t, --tag string Use a bundle in an OCI registry specified by the given tag
Expand Down
1 change: 1 addition & 0 deletions docs/content/cli/bundles_inspect.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ porter bundles inspect [flags]
```
--cnab-file string Path to the CNAB bundle.json file.
-f, --file porter.yaml Path to the Porter manifest. Defaults to porter.yaml in the current directory.
--force Force a fresh pull of the bundle
-h, --help help for inspect
-o, --output string Specify an output format. Allowed values: table, json, yaml (default "table")
-t, --tag string Use a bundle in an OCI registry specified by the given tag
Expand Down
1 change: 1 addition & 0 deletions docs/content/cli/credentials_generate.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ porter credentials generate [NAME] [flags]
--cnab-file string Path to the CNAB bundle.json file.
--dry-run Generate credential but do not save it.
-f, --file string Path to the porter manifest file. Defaults to the bundle in the current directory.
--force Force a fresh pull of the bundle
-h, --help help for generate
--tag string Use a bundle in an OCI registry specified by the given tag.
```
Expand Down
1 change: 1 addition & 0 deletions docs/content/cli/explain.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ porter explain [flags]
```
--cnab-file string Path to the CNAB bundle.json file.
-f, --file porter.yaml Path to the Porter manifest. Defaults to porter.yaml in the current directory.
--force Force a fresh pull of the bundle
-h, --help help for explain
-o, --output string Specify an output format. Allowed values: table, json, yaml (default "table")
-t, --tag string Use a bundle in an OCI registry specified by the given tag
Expand Down
1 change: 1 addition & 0 deletions docs/content/cli/inspect.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ porter inspect [flags]
```
--cnab-file string Path to the CNAB bundle.json file.
-f, --file porter.yaml Path to the Porter manifest. Defaults to porter.yaml in the current directory.
--force Force a fresh pull of the bundle
-h, --help help for inspect
-o, --output string Specify an output format. Allowed values: table, json, yaml (default "table")
-t, --tag string Use a bundle in an OCI registry specified by the given tag
Expand Down
41 changes: 41 additions & 0 deletions pkg/cnab/cnab-to-oci/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package cnabtooci

import (
"github.com/cnabio/cnab-go/bundle"
"github.com/cnabio/cnab-to-oci/relocation"
)

var _ RegistryProvider = &TestRegistry{}

type TestRegistry struct {
MockPullBundle func(tag string, insecureRegistry bool) (bun bundle.Bundle, reloMap *relocation.ImageRelocationMap, err error)
MockPushBundle func(bun bundle.Bundle, tag string, insecureRegistry bool) (reloMap *relocation.ImageRelocationMap, err error)
MockPushInvocationImage func(invocationImage string) (imageDigest string, err error)
}

func NewTestRegistry() *TestRegistry {
return &TestRegistry{}
}

func (t TestRegistry) PullBundle(tag string, insecureRegistry bool) (bundle.Bundle, *relocation.ImageRelocationMap, error) {
if t.MockPullBundle != nil {
return t.MockPullBundle(tag, insecureRegistry)
}

return bundle.Bundle{}, nil, nil
}

func (t TestRegistry) PushBundle(bun bundle.Bundle, tag string, insecureRegistry bool) (*relocation.ImageRelocationMap, error) {
if t.MockPushBundle != nil {
return t.MockPushBundle(bun, tag, insecureRegistry)
}

return nil, nil
}

func (t TestRegistry) PushInvocationImage(invocationImage string) (string, error) {
if t.MockPushInvocationImage != nil {
return t.MockPushInvocationImage(invocationImage)
}
return "", nil
}
4 changes: 2 additions & 2 deletions pkg/porter/registry.go → pkg/cnab/cnab-to-oci/provider.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package porter
package cnabtooci

import (
"github.com/cnabio/cnab-go/bundle"
"github.com/cnabio/cnab-to-oci/relocation"
)

// Registry handles talking with an OCI registry.
type Registry interface {
type RegistryProvider interface {
// PullBundle pulls a bundle from an OCI registry.
PullBundle(tag string, insecureRegistry bool) (bundle.Bundle, *relocation.ImageRelocationMap, error)

Expand Down
2 changes: 2 additions & 0 deletions pkg/cnab/cnab-to-oci/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import (
portercontext "get.porter.sh/porter/pkg/context"
)

var _ RegistryProvider = &Registry{}

type Registry struct {
*portercontext.Context
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/porter/porter.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type Porter struct {
Cache cache.BundleCache
Credentials credentials.CredentialProvider
Claims claims.ClaimProvider
Registry Registry
Registry cnabtooci.RegistryProvider
Templates *templates.Templates
Builder BuildProvider
Manifest *manifest.Manifest
Expand Down
19 changes: 11 additions & 8 deletions pkg/porter/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,27 @@ package porter

import (
"get.porter.sh/porter/pkg/cache"
cnabtooci "get.porter.sh/porter/pkg/cnab/cnab-to-oci"
"github.com/pkg/errors"
)

type BundleResolver struct {
Cache cache.BundleCache
Registry Registry
Registry cnabtooci.RegistryProvider
}

// Resolves a bundle from the cache, or pulls it and caches it
// Returns the location of the bundle or an error
func (r *BundleResolver) Resolve(opts BundlePullOptions) (cache.CachedBundle, error) {
cachedBundle, ok, err := r.Cache.FindBundle(opts.Tag)
if err != nil {
return cache.CachedBundle{}, errors.Wrapf(err, "unable to load bundle %s from cache", opts.Tag)
}
// If we found the bundle, return the path to the bundle.json
if ok && !opts.Force {
return cachedBundle, nil
if !opts.Force {
cachedBundle, ok, err := r.Cache.FindBundle(opts.Tag)
if err != nil {
return cache.CachedBundle{}, errors.Wrapf(err, "unable to load bundle %s from cache", opts.Tag)
}
// If we found the bundle, return the path to the bundle.json
if ok {
return cachedBundle, nil
}
}

b, rMap, err := r.Registry.PullBundle(opts.Tag, opts.InsecureRegistry)
Expand Down
98 changes: 98 additions & 0 deletions pkg/porter/resolver_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package porter

import (
"testing"

"get.porter.sh/porter/pkg/cache"
cnabtooci "get.porter.sh/porter/pkg/cnab/cnab-to-oci"
"get.porter.sh/porter/pkg/config"
"github.com/cnabio/cnab-go/bundle"
"github.com/cnabio/cnab-to-oci/relocation"
"github.com/stretchr/testify/assert"
)

func TestBundleResolver_Resolve_ForcePull(t *testing.T) {
tc := config.NewTestConfig(t)
testReg := cnabtooci.NewTestRegistry()
testCache := cache.NewTestCache(cache.New(tc.Config))
resolver := BundleResolver{
Cache: testCache,
Registry: testReg,
}

cacheSearched := false
testCache.FindBundleMock = func(tag string) (cache.CachedBundle, bool, error) {
cacheSearched = true
return cache.CachedBundle{}, true, nil
}

pulled := false
testReg.MockPullBundle = func(tag string, insecureRegistry bool) (bundle.Bundle, *relocation.ImageRelocationMap, error) {
pulled = true
return bundle.Bundle{}, nil, nil
}

opts := BundlePullOptions{
Force: true,
}
resolver.Resolve(opts)

assert.False(t, cacheSearched, "Force should have skipped the cache")
assert.True(t, pulled, "The bundle should have been re-pulled")
}

func TestBundleResolver_Resolve_CacheHit(t *testing.T) {
tc := config.NewTestConfig(t)
testReg := cnabtooci.NewTestRegistry()
testCache := cache.NewTestCache(cache.New(tc.Config))
resolver := BundleResolver{
Cache: testCache,
Registry: testReg,
}

cacheSearched := false
testCache.FindBundleMock = func(tag string) (cache.CachedBundle, bool, error) {
cacheSearched = true
return cache.CachedBundle{}, true, nil
}

pulled := false
testReg.MockPullBundle = func(tag string, insecureRegistry bool) (bundle.Bundle, *relocation.ImageRelocationMap, error) {
pulled = true
return bundle.Bundle{}, nil, nil
}

opts := BundlePullOptions{}
resolver.Resolve(opts)

assert.True(t, cacheSearched, "The cache should be searched when force is not specified")
assert.False(t, pulled, "The bundle should NOT be pulled because it was found in the cache")
}

func TestBundleResolver_Resolve_CacheMiss(t *testing.T) {
tc := config.NewTestConfig(t)
testReg := cnabtooci.NewTestRegistry()
testCache := cache.NewTestCache(cache.New(tc.Config))
resolver := BundleResolver{
Cache: testCache,
Registry: testReg,
}

cacheSearched := false
testCache.FindBundleMock = func(tag string) (cache.CachedBundle, bool, error) {
cacheSearched = true
return cache.CachedBundle{}, false, nil
}

pulled := false
testReg.MockPullBundle = func(tag string, insecureRegistry bool) (bundle.Bundle, *relocation.ImageRelocationMap, error) {
pulled = true
return bundle.Bundle{}, nil, nil
}

opts := BundlePullOptions{}
resolver.Resolve(opts)

assert.True(t, cacheSearched, "The cache should be searched when force is not specified")
assert.True(t, pulled, "The bundle should have been pulled because the bundle was not in the cache")
}

0 comments on commit 772ffb2

Please sign in to comment.