Skip to content
This repository has been archived by the owner on May 3, 2022. It is now read-only.

Commit

Permalink
ref(*): use bundle reference for export
Browse files Browse the repository at this point in the history
  • Loading branch information
Michelle Noorali committed Jan 25, 2019
1 parent 2af5fe4 commit 93a25e8
Show file tree
Hide file tree
Showing 19 changed files with 250 additions and 58 deletions.
2 changes: 1 addition & 1 deletion cmd/duffle/bundle_sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func bundleFileOrArg1(args []string, bundle string) (string, error) {
return "", errors.New("please specify a BUNDLE or use -f for a file")
case len(args) == 1:
// passing insecure: true, as currently we can only sign an unsinged bundle
return getBundleFilepath(args[0], true)
return getBundleFilepath(args[0], homePath(), true)
}
return bundle, nil
}
Expand Down
8 changes: 4 additions & 4 deletions cmd/duffle/credential_edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import (
"io/ioutil"
"path/filepath"

"github.com/deislabs/duffle/pkg/credentials"
"github.com/deislabs/duffle/pkg/duffle/home"

"github.com/ghodss/yaml"
"github.com/spf13/cobra"
"gopkg.in/AlecAivazis/survey.v1"
survey "gopkg.in/AlecAivazis/survey.v1"

"github.com/deislabs/duffle/pkg/credentials"
"github.com/deislabs/duffle/pkg/duffle/home"
)

const credentialEditDesc = `
Expand Down
2 changes: 1 addition & 1 deletion cmd/duffle/credential_generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ func getBundleFileFromCredentialsArg(args []string, bundleFile string, w io.Writ
case len(args) < 2 && bundleFile == "":
return "", errors.New("required arguments are NAME (name for the credentialset) and BUNDLE (CNAB bundle name) or file")
case len(args) == 2:
return getBundleFilepath(args[1], insecure)
return getBundleFilepath(args[1], homePath(), insecure)
}
return bundleFile, nil
}
44 changes: 30 additions & 14 deletions cmd/duffle/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"errors"
"fmt"
"io"
"path/filepath"

"github.com/deislabs/duffle/pkg/duffle/home"
"github.com/deislabs/duffle/pkg/loader"
"github.com/deislabs/duffle/pkg/packager"

"github.com/spf13/cobra"
Expand All @@ -29,28 +29,28 @@ images, use the --thin flag.
`

type exportCmd struct {
dest string
path string
home home.Home
out io.Writer
thin bool
verbose bool
insecure bool
bundleRef string
dest string
home home.Home
out io.Writer
thin bool
verbose bool
insecure bool
}

func newExportCmd(w io.Writer) *cobra.Command {
export := &exportCmd{out: w}

cmd := &cobra.Command{
Use: "export [PATH]",
Use: "export [BUNDLE]",
Short: "package CNAB bundle in gzipped tar file",
Long: exportDesc,
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return errors.New("this command requires the path to the bundle")
return errors.New("this command requires an argument: a bundle")
}
export.home = home.Home(homePath())
export.path = args[0]
export.bundleRef = args[0]

return export.run()
},
Expand All @@ -66,16 +66,32 @@ func newExportCmd(w io.Writer) *cobra.Command {
}

func (ex *exportCmd) run() error {
source, err := filepath.Abs(ex.path)
source, l, err := ex.setup()
if err != nil {
return err
}
if ex.Export(source, l); err != nil {
return err
}

return nil
}

l, err := getLoader(ex.insecure)
func (ex *exportCmd) setup() (string, loader.Loader, error) {
source, err := getBundleFilepath(ex.bundleRef, ex.home.String(), ex.insecure)
if err != nil {
return err
return "", nil, err
}

l, err := getLoader(ex.home.String(), ex.insecure)
if err != nil {
return "", nil, err
}

return source, l, nil
}

func (ex *exportCmd) Export(source string, l loader.Loader) error {
exp, err := packager.NewExporter(source, ex.dest, ex.home.Logs(), l, ex.thin, ex.insecure)
if err != nil {
return fmt.Errorf("Unable to set up exporter: %s", err)
Expand Down
112 changes: 112 additions & 0 deletions cmd/duffle/export_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package main

import (
"io"
"io/ioutil"
"os"
"path/filepath"
"testing"

"github.com/deislabs/duffle/pkg/duffle/home"
)

func setupTempDuffleHome(t *testing.T) (string, error) {
tempDuffleHome, err := ioutil.TempDir("", "dufflehome")
if err != nil {
return "", err
}
duffleHome := home.Home(tempDuffleHome)
if err := os.MkdirAll(duffleHome.Bundles(), 0755); err != nil {
return "", err
}
if err := os.MkdirAll(duffleHome.Logs(), 0755); err != nil {
return "", err
}
keyring := filepath.Join("..", "..", "pkg", "signature", "testdata", "keyring.gpg")

err = copyFile(keyring, filepath.Join(tempDuffleHome, "public.ring"))
if err != nil {
return "", err
}
mockSigningKeyring(tempDuffleHome, t)

return tempDuffleHome, nil
}

func TestExportSetup(t *testing.T) {
out := ioutil.Discard
tempDuffleHome, err := setupTempDuffleHome(t)
if err != nil {
t.Fatal(err)
}
defer os.Remove(tempDuffleHome)

signedBundle := filepath.Join("..", "..", "tests", "testdata", "bundles", "foo.cnab")
outfile := "foo-1.0.0.cnab"
if err = copyFile(signedBundle, filepath.Join(tempDuffleHome, "bundles", outfile)); err != nil {
t.Fatal(err)
}
var jsonBlob = []byte(`{
"foo": {
"1.0.0": "foo-1.0.0.cnab"
}
} `)
if err := ioutil.WriteFile(filepath.Join(tempDuffleHome, "repositories.json"), jsonBlob, 0644); err != nil {
t.Fatal(err)
}

// Setup a temporary dir for destination
tempDir, err := ioutil.TempDir("", "duffledest")
if err != nil {
t.Fatal(err)
}

duffleHome := home.Home(tempDuffleHome)
exp := &exportCmd{
bundleRef: "foo:1.0.0",
dest: tempDir,
home: duffleHome,
out: out,
}

source, _, err := exp.setup()
if err != nil {
t.Fatal(err)
}

expectedSource := filepath.Join(tempDuffleHome, "bundles", "foo-1.0.0.cnab")
if source != expectedSource {
t.Errorf("Expected source to be %s, got %s", expectedSource, source)
}

expFail := &exportCmd{
bundleRef: "bar:1.0.0",
dest: tempDir,
home: duffleHome,
out: out,
}
_, _, err = expFail.setup()
if err == nil {
t.Error("Expected error, got none")
}

}

func copyFile(src, dst string) (err error) {
in, err := os.Open(src)
if err != nil {
return
}
defer in.Close()

out, err := os.Create(dst)
if err != nil {
return
}
defer out.Close()

if _, err = io.Copy(out, in); err != nil {
return nil
}
return nil
}
4 changes: 2 additions & 2 deletions cmd/duffle/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ func (im *importCmd) run() error {
return err
}

dest, err := filepath.Abs(im.dest) //TODO: double check
dest, err := filepath.Abs(im.dest)
if err != nil {
return err
}

l, err := getLoader(im.insecure)
l, err := getLoader(im.home.String(), im.insecure)
if err != nil {
return err
}
Expand Down
5 changes: 2 additions & 3 deletions cmd/duffle/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ import (
"os"
"strings"

"gopkg.in/AlecAivazis/survey.v1"
"github.com/spf13/cobra"
survey "gopkg.in/AlecAivazis/survey.v1"

"github.com/deislabs/duffle/pkg/duffle/home"
"github.com/deislabs/duffle/pkg/ohai"
"github.com/deislabs/duffle/pkg/signature"

"github.com/spf13/cobra"
)

const (
Expand Down
8 changes: 4 additions & 4 deletions cmd/duffle/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ func bundleFileOrArg2(args []string, bun string, w io.Writer, insecure bool) (st
case len(args) < 2 && bun == "":
return "", errors.New("required arguments are NAME (name of the installation) and BUNDLE (CNAB bundle name) or file")
case len(args) == 2:
return getBundleFilepath(args[1], insecure)
return getBundleFilepath(args[1], homePath(), insecure)
}
return bun, nil
}
Expand All @@ -183,13 +183,13 @@ func optBundleFileOrArg2(args []string, bun string, w io.Writer, insecure bool)
// No bundle provided
return "", nil
case len(args) == 2:
return getBundleFilepath(args[1], insecure)
return getBundleFilepath(args[1], homePath(), insecure)
}
return bun, nil
}

func getBundleFilepath(bun string, insecure bool) (string, error) {
home := home.Home(homePath())
func getBundleFilepath(bun, homePath string, insecure bool) (string, error) {
home := home.Home(homePath)
ref, err := getReference(bun)
if err != nil {
return "", fmt.Errorf("could not parse reference for %s: %v", bun, err)
Expand Down
2 changes: 1 addition & 1 deletion cmd/duffle/install_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func TestGetBundle(t *testing.T) {
tc := tc // capture range variable
t.Run(tc.Name, func(t *testing.T) {
t.Parallel()
bundle, err := getBundleFilepath(tc.File, true)
bundle, err := getBundleFilepath(tc.File, duffleHome, true)
if err != nil {
t.Error(err)
}
Expand Down
6 changes: 3 additions & 3 deletions cmd/duffle/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ Example:
return cmd
}

func getLoader(insecure bool) (loader.Loader, error) {
func getLoader(home string, insecure bool) (loader.Loader, error) {
var load loader.Loader
if insecure {
load = loader.NewDetectingLoader()
} else {
kr, err := loadVerifyingKeyRings(homePath())
kr, err := loadVerifyingKeyRings(home)
if err != nil {
return nil, fmt.Errorf("cannot securely load bundle: %s", err)
}
Expand Down Expand Up @@ -88,7 +88,7 @@ func getReference(bundleName string) (reference.NamedTagged, error) {
}

func loadBundle(bundleFile string, insecure bool) (*bundle.Bundle, error) {
l, err := getLoader(insecure)
l, err := getLoader(homePath(), insecure)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/duffle/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func newShowCmd(w io.Writer) *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error {
bundleName := args[0]

bundleFile, err := getBundleFilepath(bundleName, insecure)
bundleFile, err := getBundleFilepath(bundleName, homePath(), insecure)
if err != nil {
return err
}
Expand Down
16 changes: 10 additions & 6 deletions docs/proposal/204-export-import.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,28 @@
This document covers how to export and import a bundle.

## Export
Consider the case where a user wants to create package that contains the bundle manifest along with the all of the necessary artifacts to execute the install/uninstall/lifecycle actions specified in the invocation images. You can use the `$ duffle export <path>` command to do just that.
Consider the case where a user wants to create package that contains the bundle manifest along with the all of the necessary artifacts to execute the install/uninstall/lifecycle actions specified in the invocation images. You can use the `$ duffle export [BUNDLE_REFERENCE]` command to do just that.

Duffle `export` allows a user to create a gzipped tar archive that contains the bundle manifest (signed or unisgned) along with all of the necessary images including the invocation images and the referenced images in the bundle. See example below

### Export Example
Given a directory called `wordpress/` which contains a bundle manifest (`bundle.json` or `bundle.cnab`) file:
```console
$ duffle export wordpress/ -k
$ duffle bundle list
NAME VERSION DIGEST SIGNED?
helloworld 0.1.1 92145d4132aba06e11940a79f20402a3621196f1 true
wordpress 0.2.0 b91550cfc20bd21929e48b21c88715c9e89349eb true

$ duffle export wordpress:0.2.0
$ ls
wordpress/ wordpress-0.2.0.tgz
wordpress-0.2.0.tgz
```

For this example, we're passing in the `-k` flag allowing us to export an unsigned/insecure bundle. The default behavior (without `-k`) of export is to only package signed bundles.
You can pass in the `-k` flag to export an unsigned/insecure bundle or skip verification of a signed bundle. The default behavior (without `-k`) of export is to only package signed bundles after verifying the signature.

In the example, you'll find the exported artifact, a gzipped tar archive: `wordpress-0.2.0.tgz`. Unpacking that artifact results in the following directory structure:
```
wordpress-0.2.0/
bundle.json
bundle.cnab
artifacts/
cnab-wordpress-0.2.0.tar
```
Expand Down
Loading

0 comments on commit 93a25e8

Please sign in to comment.