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

Feat: bundle outputs #438

Merged
merged 17 commits into from
Jul 11, 2019
Merged

Feat: bundle outputs #438

merged 17 commits into from
Jul 11, 2019

Conversation

vdice
Copy link
Member

@vdice vdice commented Jul 1, 2019

This PR adds:

  • functionality to parse a new outputs section in a porter manifest (Note: the current implementation requires a mixin-specific step/action output to be declared before it can be exposed/used as a bundle-level output.)
  • functionality to place output values under /cnab/app/outputs in the execution environment, per the CNAB Spec (outputs are currently written only when added under the new outputs section and the optional applyTo specification doesn't conflict)
  • functionality to place these same outputs under the local/user's $PORTER_HOME/outputs/<bundle name> directory, assuming the default Docker driver is being used
  • cli command: porter bundle show to list a bundle's claim and outputs

TODO:

  • add a cli command that users can invoke to print outputs from the corresponding local file (question around AC posed in [Spec]: Support CNAB Bundle Outputs #344 (comment))
  • add unit tests for logic added in run.go
  • docker driver bind mount refactor/units
  • update the base porters schema template to include the outputs section
  • add/update docs

@vdice vdice force-pushed the feat/bundle-outputs branch 2 times, most recently from de619e6 to 759d16d Compare July 3, 2019 18:11
@vdice
Copy link
Member Author

vdice commented Jul 3, 2019

In the most recent commit, I went ahead and added the cli commands mentioned/proposed in #344 (comment)

@vdice vdice marked this pull request as ready for review July 8, 2019 16:42
@vdice
Copy link
Member Author

vdice commented Jul 8, 2019

Putting into 'ready for review' while I finish up unit tests...

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.

I'm not done with the review but wanted to get you thinking about maybe moving the command into a different spot.

build/testdata/bundles/wordpress/porter.yaml Outdated Show resolved Hide resolved
build/testdata/bundles/wordpress/porter.yaml Outdated Show resolved Hide resolved
build/testdata/bundles/wordpress/porter.yaml Outdated Show resolved Hide resolved

func buildOutputsCommand(p *porter.Porter) *cobra.Command {
cmd := &cobra.Command{
Use: "outputs",
Copy link
Member

Choose a reason for hiding this comment

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

I think that this would be better not as a standalone command but as a task-based command that is used to inspect an installed bundle.

So instead of having porter outputs -b bundle name (which is off anyway because we are actually working with claim names right?), what if we had a command that let you look at an installed bundle and also had it dig deeper into additional available into (like outputs) if the bundle had it?

Maybe something like this:

$ porter bundles list
NAME                  CREATED      MODIFIED     LAST ACTION   LAST STATUS
mysql                  2019-06-24   2019-06-24   install       success

$ porter bundle show mysql
Name          mysql
Created       2019-06-24
Modified      2019-06-24
Last Action  install
Last Status  success

Outputs
=====================================================================
Name           Type         Value
-----------+--------+--------------------------------------------------------+
hostName     String          wpmysql
port                Integer       5423
clientCert       String         /Users/carolynvs/.porter/outputs/.../mysql/clientCert

clientCert is writeOnly so we don't display it. Find some logic for not dumping sensitive or giant info

Copy link
Member Author

@vdice vdice Jul 8, 2019

Choose a reason for hiding this comment

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

Roger; I can switch tactics and implement porter bundle show [NAME] to show bundle/claim deets, including outputs.

Should we leave this PR with that command or do we also want a solution/command for getting a particular output value? (Perhaps to merely echo/print or perhaps to send to a file, etc.)

Copy link
Member

Choose a reason for hiding this comment

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

If someone wants to just get a single output value, I would encourage them to use the --output json and then use jq or something to grab what they need. Maybe we can start with that for now and see if people want a more specialize command like porter bundle output list/show to work directly with outputs. We may never need to implement it, depending on lack of asks/feedback.

How does that sound?

Copy link
Member Author

Choose a reason for hiding this comment

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

That sounds good to me. My only question revolves around the case when an actual output value is large (think: kubeconfig file) while listing. Shall we just default to truncating all values at a certain character limit when printing via default/table and print the entire value if the printing option is otherwise (yaml or json)?

Copy link
Member

Choose a reason for hiding this comment

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

Let's start with truncating at certain number of characters and see how well that works.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, updated to limit cli scope to just the porter bundle show command. Please take a look when convenient.

cmd/porter/outputs.go Outdated Show resolved Hide resolved
cmd/porter/outputs.go Outdated Show resolved Hide resolved
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.

This PR will also need to update the base porters schema template to include the outputs section

@vdice vdice force-pushed the feat/bundle-outputs branch 4 times, most recently from fa0cae3 to 03d18f8 Compare July 10, 2019 00:44
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.

Still working through the PR. Looking good but thought that I'd give some more feedback while I keep reviewing.

uninstall:
- kubernetes:
description: "Uninstall Hello World"
manifests:
Copy link
Member

Choose a reason for hiding this comment

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

nice catch! 😅

)

type Provider interface {
Copy link
Member

Choose a reason for hiding this comment

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

This interface is defined in the package that uses it (not the packge that implements it) which is a bit of a "go ism". So you should remove this interface declaration here, and move FetchClaim to pkg/porter/cnab.go CNABProvider

@@ -34,5 +43,41 @@ func (d *Duffle) newDriver(driverName string) (driver.Driver, error) {
configurable.SetConfig(driverCfg)
}

// If docker driver, setup host bind mount for outputs
// TODO: separate function/add tests
if dockerish, ok := driverImpl.(*duffledriver.DockerDriver); ok {
Copy link
Member

Choose a reason for hiding this comment

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

It would be nice to see this logic separated into a function (like pkg/cnab/provider/credentials.go loadCredentials).

Copy link
Member Author

Choose a reason for hiding this comment

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

Separated, though unfortunately we can't yet test as thoroughly as we'd wish (no access yet to the docker driver configuration options... TODO note added.)


// Create outputs sub-directory using the bundle name
bundleOutputsDir := filepath.Join(outputsDir, claimName)
err = d.FileSystem.MkdirAll(bundleOutputsDir, 0755)
Copy link
Member

Choose a reason for hiding this comment

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

I think the permissions on that folder may be wrong, because it lets anyone on the machine read outputs created by the bundle. Let's do a sweep on permissions in a separate issue. I'll make one so that we can use a variable for this stuff going forward.

Copy link
Member Author

Choose a reason for hiding this comment

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

I've changed to os.ModePerm for now... w/ intentions to follow-up across codebase in issue you've mentioned...

return driverImpl, err
}

func (d *Duffle) FetchClaim(name string) (*claim.Claim, error) {
Copy link
Member

Choose a reason for hiding this comment

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

👍

}

type TestStore struct {
backingStore map[string][]byte
Copy link
Member

Choose a reason for hiding this comment

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

I feel bad because you implemented all of this but I'm pretty sure we could have also used afero here and not written a test backing store at all. It would be an afero in memory file system from the test context (which we got from the constructor of the TestDuffle) and then the existing crud claim store.

I think that would be preferable to reimplementing another claim store? Let me know i you'd like to collaborate quick on how to use afero to do that.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops! Good call; using afero was the way to go. This file has since been removed.

return errors.New("output name is required")
}

// TODO: Validate inline Schema
Copy link
Member

Choose a reason for hiding this comment

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

Haha, yeah that's a big task on our plate in general for CNAB 1.0 no need to tackle it as part of this PR. 😀

return errors.Wrap(err, "unable to get outputs directory")
}

err = p.FileSystem.MkdirAll(outputsDir, 0755)
Copy link
Member

Choose a reason for hiding this comment

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

I'm a bit unsure of the code's intent right here? This function is meant to create files on the local file system in pwd/.cnab in preparation before building the invocation image.

If we need to make the outputs directory ahead of time, then the code should be doing this:

p.FileSystem.MkdirAll(filepath.Join(build.LOCAL_APP, "outputs"), 0755)

Otherwise if your intent was to make sure the outputs directory in PORTER_HOME exists before the bundle is run (which is what this code is doing), then it's in the wrong spot. It should be located in maybe pkg/porter/options.go applyDefaultOptions or really a new function that is executed in each function before calling the cnab provider functions for install/upgrade/etc.

Copy link
Member Author

Choose a reason for hiding this comment

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

You know, I think we're okay with not ensuring the outputs directory exists before a bundle is run. The logic around setting up the volume mount (if driver is the default Docker driver) is sufficient (will create ${PORTER_HOME}/outputs if it doesn't already exist, in addition to the <claim name> subdir.)

So, I've removed for now.

@@ -40,6 +40,8 @@ func (l CondensedClaimList) Less(i, j int) bool {

// ListBundles lists installed bundles using the printer.Format provided
func (p *Porter) ListBundles(opts printer.PrintOptions) error {
// TODO: supply cnab.Provider interface as second arg, use to access ClaimStore
Copy link
Member

Choose a reason for hiding this comment

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

Once you move FetchClaim like I suggested above, then you will immediate have access to it, because CNABProvider is already on the Porter receiver here.

@vdice
Copy link
Member Author

vdice commented Jul 10, 2019

Ok, latest commits are up intending to address all feedback.

Lemme know if there are any outstanding items; otherwise I/we can squash commits and merge when ready.

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.

This is good to merge. You've got a ton of commits but I wasn't sure if you wanted to do one big squash or an artisanal rebase. Up to you, feel free to merge at will! 👍

@vdice vdice merged commit c3908ac into getporter:master Jul 11, 2019
@vdice vdice deleted the feat/bundle-outputs branch July 11, 2019 00:38
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