Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Publish bundles and Allow Install From Tag #379

Merged
merged 9 commits into from
Jun 5, 2019

Conversation

jeremyrickard
Copy link
Contributor

This PR starts down the road of implementing a bundle cache per #322. It doesn't fully implement that issue, but lays some groundwork.

The major addition here is that users can now porter publish a bundle to an OCI registry using cnab-to-oci and install a bundle from an OCI registry using a new --tag flag on porter install:

porter install --tag jeremyrickard/porter-kube-bundle:1.0 -c kool-kred
installing HELLO...
executing porter install configuration from /cnab/app/porter.yaml
Install Hello World App

When the --tag flag is provided, Porter will attempt to locate the specified bundle in the new ~/.porter/cache directory using the hashed tag name as a directory key. If it is not found, it is pulled with cnab-to-oci, stored in the cache, and the new path in the cache is returned and used to update the install opts. If it is found, the cached path is returned.

Sorry this is rather large.

@jeremyrickard jeremyrickard self-assigned this Jun 4, 2019
f.StringVarP(&opts.Tag, "tag", "t", "",
"Install from a bundle in an OCI registry specified by the given tag")
f.BoolVar(&opts.InsecureRegistry, "insecure-registry", false,
"Treat the given bundle registry as insecure")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we improve this error message a bit? Based on what you told me, I think it means "Allow connecting to a registry that isn't secured with TLS certificates" or something like that, no?

@@ -288,7 +291,7 @@ func buildBundlePublishCommand(p *porter.Porter) *cobra.Command {

f := cmd.Flags()
f.StringVarP(&opts.File, "file", "f", "", "Path to the Porter manifest. Defaults to `porter.yaml` in the current directory.")
f.StringVarP(&opts.Tag, "tag", "t", "", "Tag to apply to the CNAB bundle. Defaults to the `Tag` value currently in the Porter manifest.")
f.BoolVar(&opts.InsecureRegistry, "insecure", false, "Treat the registry as insecure.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note that whatever we change the flag description to above, let's change this one as well.


* This needs to wait until bundle registries is figured out
Before you can publish your bundle, you must first run a `porter build` command. This will create the invocation image so it can be pushed to an OCI (Docker) registry along with your CNAB bundle manifest. It's a good idea to work with your bundle and test it locally before you decide to publish it to a registry.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: "before you decide to publish" -> "before you publish"

## Bundle Publish

Once you are satisfied with the bundle, the next step is to publish the bundle! Bundle publishing involves pushing the both the invocation image and the CNAB bundle manifest to an OCI registry. Porter uses [docker tags](https://docs.docker.com/engine/reference/commandline/tag/) for both nvocation images and CNAB bundle manifests. These are defined in your `porter.yaml` file:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spelling: "nvocation images" -> "invocation images"

```

This YAML snippet indicates that the invocation image will be built and tagged as `deislabs/porter-kubernetes:latest`. The first part of this reference, `deislabs` indicates the registry that the invocation image should eventually be published to. The `porter-kubernetes` segment identifies the iamge, while the `:latest` portion denotes a specific version. Much like the `invocationImage` attribute is used to control the name of resulting Docker invocation image, the `tag` attribute is used to specify the name and location of the resulting CNAB bundle. In both cases, when you are ready to publish your bundle, it would be a good idea to provide specific versions for both of these, such as `v1.0.0`. We recommend using [semantic versioning](https://semver.org/) for both the invocation image and the bundle. We also recommend specifying the same registry for both, in order to simplify access to your bundle and invocation image by end users.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spelling: "iamge"

bid := getBundleID(bundleTag)
bundleCnabDir, err := c.getCachedBundleCNABDir(bid)
cachedBundlePath := filepath.Join(bundleCnabDir, "bundle.json")
c.FileSystem.MkdirAll(bundleCnabDir, os.ModePerm)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't checking for an error

// hash the tag, tags have characters that won't work as part of a path
// so hashing here to get a path friendly name
bid := md5.Sum([]byte(bundleTag))
return fmt.Sprintf("%x", bid)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also use hex.EncodeToString. Not sure if that's better or not, or if fmt uses that under the hood. It may be more clear though.

@@ -46,6 +64,21 @@ func (o *InstallOptions) ToDuffleArgs() cnabprovider.InstallArguments {
// InstallBundle accepts a set of pre-validated InstallOptions and uses
// them to install a bundle.
func (p *Porter) InstallBundle(opts InstallOptions) error {
// If opts.Tag is set, fetch the bundle
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you had to put this here because there's a bug in applyDefaultOptions. It assumes there there is always a porter.yaml to load. Heads up that I'm fixing that as part of the work I'm doing today on rebuilding before actions when the hash is out of date.

@@ -89,6 +90,7 @@ func TestInstallOptions_validateParams(t *testing.T) {
sharedOptions{
Params: []string{"A=1", "B=2"},
},
BundlePullOptions{},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you declared InstallOptions with BundlePullOptions as an embedded type (and not a pointer), you don't need to have this line here. Same for the other tests below. I

The only time you need stuff like this line here is if you defined it like this instead

type InstallOptions struct {
  *BundlePullOptions
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huh, the compiler complained until I added this.

pwd, err := os.Getwd()
if err != nil {
return errors.Wrap(err, "could not get current working directory")
}
f = filepath.Join(pwd, config.Name)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I notice that we are duplicating validation between sharedOptions and here. As part of my --cnab-file work, I'm making another struct that is going to extract out logic for --file and --cnab-file that will do the common validation for these flags across all the commands. Just a heads up.

Copy link
Member

@carolynvs carolynvs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

YES! Can't wait to have this in Porter. SHIP. IT. ⛵️

@jeremyrickard jeremyrickard merged commit 1a9c6e8 into getporter:master Jun 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants