Skip to content
This repository has been archived by the owner on Jun 13, 2021. It is now read-only.

Feat run labels #715

Merged
merged 3 commits into from
Oct 31, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions cmd/cnab-run/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ func installAction(instanceName string) error {
if err != nil {
return err
}
if err = addLabels(rendered); err != nil {
return err
}
addAppLabels(rendered, instanceName)

if err := os.Chdir(app.Path); err != nil {
return err
}
Expand Down Expand Up @@ -87,6 +91,27 @@ func getBundleImageMap() (map[string]bundle.Image, error) {
return result, nil
}

func addLabels(rendered *composetypes.Config) error {
args, err := ioutil.ReadFile(internal.DockerArgsPath)
if err != nil {
return err
}
var a packager.DockerAppArgs
if err := json.Unmarshal(args, &a); err != nil {
return err
}
for k, v := range a.Labels {
for i, service := range rendered.Services {
if service.Labels == nil {
service.Labels = map[string]string{}
}
service.Labels[k] = v
rendered.Services[i] = service
}
}
return nil
}

func addAppLabels(rendered *composetypes.Config, instanceName string) {
for i, service := range rendered.Services {
if service.Labels == nil {
Expand Down
25 changes: 25 additions & 0 deletions e2e/commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,31 @@ func TestRunOnlyOne(t *testing.T) {
})
}

func TestRunWithLabels(t *testing.T) {
runWithDindSwarmAndRegistry(t, func(info dindSwarmAndRegistryInfo) {
cmd := info.configuredCmd

contextPath := filepath.Join("testdata", "simple")
cmd.Command = dockerCli.Command("app", "build", "--tag", "myapp", contextPath)
icmd.RunCmd(cmd).Assert(t, icmd.Success)

cmd.Command = dockerCli.Command("app", "run", "myapp", "--name", "myapp", "--label", "label.key=labelValue")
icmd.RunCmd(cmd).Assert(t, icmd.Success)

services := []string{
"myapp_db", "myapp_web", "myapp_api",
}
for _, service := range services {
fmt.Printf("%q", service)
cmd.Command = dockerCli.Command("inspect", service)
icmd.RunCmd(cmd).Assert(t, icmd.Expected{
ExitCode: 0,
Out: `"label.key": "labelValue"`,
})
}
})
}

func TestDockerAppLifecycle(t *testing.T) {
t.Run("withBindMounts", func(t *testing.T) {
testDockerAppLifecycle(t, true)
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/image/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func printImageIDs(dockerCli command.Cli, refs []pkg) error {
}
fmt.Fprintln(&buf, stringid.TruncateID(id.String()))
}
fmt.Fprintf(dockerCli.Out(), buf.String())
fmt.Fprint(dockerCli.Out(), buf.String())
return nil
}

Expand Down
6 changes: 0 additions & 6 deletions internal/commands/image/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@ import (
"github.com/docker/distribution/reference"
)

type mockRef string

func (ref mockRef) String() string {
return string(ref)
}

type bundleStoreStubForListCmd struct {
refMap map[reference.Reference]*bundle.Bundle
// in order to keep the reference in the same order between tests
Expand Down
23 changes: 23 additions & 0 deletions internal/commands/parameters.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package commands

import (
"encoding/json"
"fmt"
"io"
"os"
"strings"

"github.com/deislabs/cnab-go/bundle"
"github.com/docker/app/internal"
"github.com/docker/app/internal/packager"
"github.com/docker/app/internal/store"
"github.com/docker/app/types/parameters"
cliopts "github.com/docker/cli/opts"
Expand Down Expand Up @@ -45,6 +47,27 @@ func withCommandLineParameters(overrides []string) mergeBundleOpt {
}
}

func withLabels(labels []string) mergeBundleOpt {
rumpl marked this conversation as resolved.
Show resolved Hide resolved
return func(c *mergeBundleConfig) error {
for _, l := range labels {
if strings.HasPrefix(l, internal.Namespace) {
return errors.Errorf("labels cannot start with %q", internal.Namespace)
}
rumpl marked this conversation as resolved.
Show resolved Hide resolved
}
l := packager.DockerAppArgs{
Labels: cliopts.ConvertKVStringsToMap(labels),
}
out, err := json.Marshal(l)
if err != nil {
return err
}
if _, ok := c.bundle.Parameters[internal.ParameterArgs]; ok {
c.params[internal.ParameterArgs] = string(out)
}
return nil
}
}

func withSendRegistryAuth(sendRegistryAuth bool) mergeBundleOpt {
return func(c *mergeBundleConfig) error {
if _, ok := c.bundle.Definitions[internal.ParameterShareRegistryCredsName]; ok {
Expand Down
11 changes: 7 additions & 4 deletions internal/commands/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type runOptions struct {
kubeNamespace string
stackName string
cnabBundle string
labels []string
}

const longDescription = `Run an App from an App image.`
Expand Down Expand Up @@ -59,10 +60,11 @@ func runCmd(dockerCli command.Cli) *cobra.Command {
}
opts.parametersOptions.addFlags(cmd.Flags())
opts.credentialOptions.addFlags(cmd.Flags())
cmd.Flags().StringVar(&opts.orchestrator, "orchestrator", "", "Orchestrator to run on (swarm, kubernetes)")
cmd.Flags().StringVar(&opts.kubeNamespace, "namespace", "default", "Kubernetes namespace in which to run the App")
cmd.Flags().StringVar(&opts.stackName, "name", "", "Name of the running App")
cmd.Flags().StringVar(&opts.cnabBundle, "cnab-bundle-json", "", "Run a CNAB bundle instead of a Docker App image")
cmd.Flags().StringVar(&opts.orchestrator, "orchestrator", "", "Orchestrator to install on (swarm, kubernetes)")
cmd.Flags().StringVar(&opts.kubeNamespace, "namespace", "default", "Kubernetes namespace to install into")
cmd.Flags().StringVar(&opts.stackName, "name", "", "Assign a name to the installation")
cmd.Flags().StringVar(&opts.cnabBundle, "cnab-bundle-json", "", "Run a CNAB bundle instead of a Docker App")
cmd.Flags().StringArrayVar(&opts.labels, "label", nil, "Label to add to services")

return cmd
}
Expand Down Expand Up @@ -130,6 +132,7 @@ func runBundle(dockerCli command.Cli, bndl *bundle.Bundle, opts runOptions, ref
if err := mergeBundleParameters(installation,
withFileParameters(opts.parametersFiles),
withCommandLineParameters(opts.overrides),
withLabels(opts.labels),
withOrchestratorParameters(opts.orchestrator, opts.kubeNamespace),
withSendRegistryAuth(opts.sendRegistryAuth),
); err != nil {
Expand Down
4 changes: 4 additions & 0 deletions internal/names.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ const (
ParameterRenderFormatName = Namespace + "render-format"
// ParameterInspectFormatName is the name of the parameter containing the inspect format
ParameterInspectFormatName = Namespace + "inspect-format"
// ParameterArgs is the name of the parameter containing labels to be applied to service containers
ParameterArgs = Namespace + "args"
// ParameterShareRegistryCredsName is the name of the parameter which indicates if credentials should be shared
ParameterShareRegistryCredsName = Namespace + "share-registry-creds"

Expand All @@ -68,6 +70,8 @@ const (
// the inspect output format.
DockerInspectFormatEnvVar = "DOCKER_INSPECT_FORMAT"

DockerArgsPath = "/cnab/app/args.json"

// CustomDockerAppName is the custom variable set by Docker App to
// save custom informations
CustomDockerAppName = "com.docker.app"
Expand Down
23 changes: 23 additions & 0 deletions internal/packager/cnab.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,24 @@ type DockerAppCustom struct {
Payload json.RawMessage `json:"payload,omitempty"`
}

// DockerAppArgs represent the object passed to the invocation image
// by Docker App.
type DockerAppArgs struct {
// Labels are the labels to add to containers on run
Labels map[string]string `json:"labels,omitempty"`
}

// ToCNAB creates a CNAB bundle from an app package
func ToCNAB(app *types.App, invocationImageName string) (*bundle.Bundle, error) {
mapping := ExtractCNABParameterMapping(app.Parameters())
flatParameters := app.Parameters().Flatten()
definitions := definition.Definitions{
internal.ParameterArgs: {
Type: "string",
Default: "",
Title: "Arguments",
Description: "Arguments that are passed by file to the invocation image",
},
internal.ParameterOrchestratorName: {
Type: "string",
Enum: []interface{}{
Expand Down Expand Up @@ -73,6 +86,16 @@ func ToCNAB(app *types.App, invocationImageName string) (*bundle.Bundle, error)
},
}
parameters := map[string]bundle.Parameter{
internal.ParameterArgs: {
Destination: &bundle.Location{
Path: internal.DockerArgsPath,
},
ApplyTo: []string{
"install",
"upgrade",
},
Definition: internal.ParameterArgs,
},
internal.ParameterOrchestratorName: {
Destination: &bundle.Location{
EnvironmentVariable: internal.DockerStackOrchestratorEnvVar,
Expand Down
16 changes: 16 additions & 0 deletions internal/packager/testdata/bundle-json.golden
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@
"io.cnab.status": {}
},
"parameters": {
"com.docker.app.args": {
"definition": "com.docker.app.args",
"applyTo": [
"install",
"upgrade"
],
"destination": {
"path": "/cnab/app/args.json"
}
},
"com.docker.app.inspect-format": {
"definition": "com.docker.app.inspect-format",
"applyTo": [
Expand Down Expand Up @@ -115,6 +125,12 @@
}
},
"definitions": {
"com.docker.app.args": {
"default": "",
"description": "Arguments that are passed by file to the invocation image",
"title": "Arguments",
"type": "string"
},
"com.docker.app.inspect-format": {
"default": "json",
"description": "Output format for the inspect command",
Expand Down