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

Commit

Permalink
Add injected-files into invocation images (#298)
Browse files Browse the repository at this point in the history
This allows invocation images requiring settings files to work
correctly.
e-g: for docker-app invocation image, you can use settings files to
provide templated parameters. This is important, as this invocation
image as a setting management that is case-sensitive, and depending on
which docker-app package you want to deploy, the settings to pass can be
different.
This would also make it easier to create a generic Helm invocation image
(e.g.: we can mount settings files, or even an helm chart in tarball
format to the invocation image)

Signed-off-by: Simon Ferquel <[email protected]>
  • Loading branch information
simonferquel authored and Matthew Fisher committed Oct 30, 2018
1 parent 14fda2c commit 90555af
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 11 deletions.
61 changes: 58 additions & 3 deletions cmd/duffle/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,19 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"path/filepath"
"strings"

"github.com/deis/duffle/pkg/signature"

"github.com/deis/duffle/pkg/action"
"github.com/deis/duffle/pkg/bundle"
"github.com/deis/duffle/pkg/claim"
"github.com/deis/duffle/pkg/duffle/home"
"github.com/deis/duffle/pkg/loader"
"github.com/deis/duffle/pkg/reference"

"github.com/deis/duffle/pkg/signature"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
Expand Down Expand Up @@ -61,6 +60,8 @@ For unpublished CNAB bundles, you can also load the bundle.json directly:
bundleFile string
setParams []string
insecure bool
setFiles []string
setFilesContent []string

installationName string
bun *bundle.Bundle
Expand Down Expand Up @@ -108,6 +109,10 @@ For unpublished CNAB bundles, you can also load the bundle.json directly:
if err != nil {
return err
}
c.Files, err = calculateInjectedFiles(bun, setFiles, setFilesContent)
if err != nil {
return err
}

inst := &action.Install{
Driver: driverImpl,
Expand All @@ -133,6 +138,8 @@ For unpublished CNAB bundles, you can also load the bundle.json directly:
flags.StringVarP(&valuesFile, "parameters", "p", "", "Specify file containing parameters. Formats: toml, MORE SOON")
flags.StringVarP(&bundleFile, "file", "f", "", "Bundle file to install")
flags.StringArrayVarP(&setParams, "set", "s", []string{}, "Set individual parameters as NAME=VALUE pairs")
flags.StringArrayVarP(&setFiles, "inject-file", "i", []string{}, "Set injected files as NAME=SOURCE-PATH pairs")
flags.StringArrayVar(&setFilesContent, "inject-file-content", []string{}, "Set injected files as NAME=CONTENT pairs")
return cmd
}

Expand Down Expand Up @@ -322,3 +329,51 @@ func calculateParamValues(bun *bundle.Bundle, valuesFile string, setParams []str
}
return bundle.ValuesOrDefaults(vals, bun)
}

func calculateInjectedFiles(bun *bundle.Bundle, setFilePaths []string, setFileContents []string) (map[string]string, error) {
remainingRequired := map[string]struct{}{}
result := map[string]string{}
for k, v := range bun.Files {
if v.Required {
remainingRequired[k] = struct{}{}
}
}
for _, p := range setFilePaths {
parts := strings.SplitN(p, "=", 2)
if len(parts) != 2 {
return nil, fmt.Errorf("malformed injected file path parameter: %q", p)
}
if _, ok := result[parts[0]]; ok {
return nil, fmt.Errorf("ambiguous content for file %q", parts[0])
}
content, err := ioutil.ReadFile(parts[1])
if err != nil {
return nil, fmt.Errorf("error while reading file %q: %s", parts[1], err)
}
result[parts[0]] = string(content)
delete(remainingRequired, parts[0])
}

for _, p := range setFileContents {
parts := strings.SplitN(p, "=", 2)
if len(parts) != 2 {
return nil, fmt.Errorf("malformed injected file path parameter: %q", p)
}
if _, ok := result[parts[0]]; ok {
return nil, fmt.Errorf("ambiguous content for file %q", parts[0])
}
result[parts[0]] = parts[1]
delete(remainingRequired, parts[0])
}

if len(remainingRequired) == 0 {
return result, nil
}

var missingRequired []string
for k := range remainingRequired {
missingRequired = append(missingRequired, k)
}

return nil, fmt.Errorf("the following required files are not set: %s", strings.Join(missingRequired, ", "))
}
23 changes: 16 additions & 7 deletions cmd/duffle/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import (
"errors"
"fmt"

"github.com/spf13/cobra"

"github.com/deis/duffle/pkg/action"
"github.com/spf13/cobra"
)

const upgradeUsage = `perform the upgrade action in the CNAB bundle`
Expand All @@ -28,10 +27,12 @@ var upgradeDriver string

type upgradeCmd struct {
duffleCmd
name string
valuesFile string
setParams []string
insecure bool
name string
valuesFile string
setParams []string
insecure bool
setFiles []string
setFilesContent []string
}

func newUpgradeCmd() *cobra.Command {
Expand Down Expand Up @@ -69,7 +70,8 @@ func newUpgradeCmd() *cobra.Command {
flags.StringVarP(&uc.valuesFile, "parameters", "p", "", "Specify file containing parameters. Formats: toml, MORE SOON")
flags.StringArrayVarP(&uc.setParams, "set", "s", []string{}, "Set individual parameters as NAME=VALUE pairs")
flags.BoolVarP(&uc.insecure, "insecure", "k", false, "Do not verify the bundle (INSECURE)")

flags.StringArrayVarP(&uc.setFiles, "inject-file", "i", []string{}, "Set injected files as NAME=SOURCE-PATH pairs")
flags.StringArrayVar(&uc.setFilesContent, "inject-file-content", []string{}, "Set injected files as NAME=CONTENT pairs")
return cmd
}

Expand Down Expand Up @@ -107,6 +109,13 @@ func (up *upgradeCmd) upgrade(credentialsFile, bundleFile string) error {
}
}

if len(up.setFilesContent) > 0 || len(up.setFiles) > 0 {
claim.Files, err = calculateInjectedFiles(claim.Bundle, up.setFiles, up.setFilesContent)
if err != nil {
return err
}
}

upgr := &action.Upgrade{
Driver: driverImpl,
}
Expand Down
5 changes: 4 additions & 1 deletion pkg/action/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"strings"

"github.com/deis/duffle/pkg/bundle"

"github.com/deis/duffle/pkg/claim"
"github.com/deis/duffle/pkg/credentials"
"github.com/deis/duffle/pkg/driver"
Expand Down Expand Up @@ -42,6 +41,10 @@ func selectInvocationImage(d driver.Driver, c *claim.Claim) (bundle.InvocationIm

func opFromClaim(action string, c *claim.Claim, ii bundle.InvocationImage, creds credentials.Set, w io.Writer) *driver.Operation {
env, files := creds.Flatten()
for k, v := range c.Files {
files[c.Bundle.Files[k].Path] = v
}

return &driver.Operation{
Action: action,
Installation: c.Name,
Expand Down
8 changes: 8 additions & 0 deletions pkg/bundle/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ type CredentialLocation struct {
EnvironmentVariable string `json:"env" toml:"env"`
}

// FileLocation contains the location of a file the the invocation image
// can use
type FileLocation struct {
Path string `json:"path" toml:"path"`
Required bool `json:"required" toml:"required"`
}

// Maintainer describes a code maintainer of a bundle
type Maintainer struct {
// Name is a user name or organization name
Expand All @@ -97,6 +104,7 @@ type Bundle struct {
Images []Image `json:"images" toml:"images"`
Parameters map[string]ParameterDefinition `json:"parameters" toml:"parameters"`
Credentials map[string]CredentialLocation `json:"credentials" toml:"credentials"`
Files map[string]FileLocation `json:"files" toml:"files"`
}

// ValuesOrDefaults returns parameter values or the default parameter values
Expand Down
1 change: 1 addition & 0 deletions pkg/claim/claim.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type Claim struct {
Bundle *bundle.Bundle `json:"bundle"`
Result Result `json:"result"`
Parameters map[string]interface{} `json:"parameters"`
Files map[string]string `json:"files"`
}

// ValidName is a regular expression that indicates whether a name is a valid claim name.
Expand Down

0 comments on commit 90555af

Please sign in to comment.