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

Adding network specific option in csv format for service create/update #62

Merged
merged 3 commits into from
May 18, 2017
Merged
Show file tree
Hide file tree
Changes from all 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
20 changes: 10 additions & 10 deletions cli/command/service/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,17 +396,18 @@ func (c *credentialSpecOpt) Value() *swarm.CredentialSpec {
return c.value
}

func convertNetworks(ctx context.Context, apiClient client.NetworkAPIClient, networks []string) ([]swarm.NetworkAttachmentConfig, error) {
nets := []swarm.NetworkAttachmentConfig{}
for _, networkIDOrName := range networks {
network, err := apiClient.NetworkInspect(ctx, networkIDOrName, false)
func convertNetworks(ctx context.Context, apiClient client.NetworkAPIClient, networks opts.NetworkOpt) ([]swarm.NetworkAttachmentConfig, error) {
var netAttach []swarm.NetworkAttachmentConfig
for _, net := range networks.Value() {
networkIDOrName := net.Target
_, err := apiClient.NetworkInspect(ctx, networkIDOrName, false)
if err != nil {
return nil, err
}
nets = append(nets, swarm.NetworkAttachmentConfig{Target: network.ID})
netAttach = append(netAttach, swarm.NetworkAttachmentConfig{Target: net.Target, Aliases: net.Aliases, DriverOpts: net.DriverOpts})
}
sort.Sort(byNetworkTarget(nets))
return nets, nil
sort.Sort(byNetworkTarget(netAttach))
return netAttach, nil
}

type endpointOptions struct {
Expand Down Expand Up @@ -539,7 +540,7 @@ type serviceOptions struct {
placementPrefs placementPrefOpts
update updateOptions
rollback updateOptions
networks opts.ListOpts
networks opts.NetworkOpt
endpoint endpointOptions

registryAuth bool
Expand All @@ -565,7 +566,6 @@ func newServiceOptions() *serviceOptions {
dnsOption: opts.NewListOpts(nil),
dnsSearch: opts.NewListOpts(opts.ValidateDNSSearch),
hosts: opts.NewListOpts(opts.ValidateExtraHost),
networks: opts.NewListOpts(nil),
}
}

Expand Down Expand Up @@ -627,7 +627,7 @@ func (opts *serviceOptions) ToService(ctx context.Context, apiClient client.Netw
return service, err
}

networks, err := convertNetworks(ctx, apiClient, opts.networks.GetAll())
networks, err := convertNetworks(ctx, apiClient, opts.networks)
if err != nil {
return service, err
}
Expand Down
4 changes: 2 additions & 2 deletions cli/command/service/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -1028,8 +1028,8 @@ func updateNetworks(ctx context.Context, apiClient client.NetworkAPIClient, flag
}

if flags.Changed(flagNetworkAdd) {
values := flags.Lookup(flagNetworkAdd).Value.(*opts.ListOpts).GetAll()
networks, err := convertNetworks(ctx, apiClient, values)
values := flags.Lookup(flagNetworkAdd).Value.(*opts.NetworkOpt)
networks, err := convertNetworks(ctx, apiClient, *values)
if err != nil {
return err
}
Expand Down
106 changes: 106 additions & 0 deletions opts/network.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package opts

import (
"encoding/csv"
"fmt"
"regexp"
"strings"
)

const (
networkOptName = "name"
networkOptAlias = "alias"
driverOpt = "driver-opt"
)

// NetworkAttachmentOpts represents the network options for endpoint creation
type NetworkAttachmentOpts struct {
Target string
Aliases []string
DriverOpts map[string]string
}

// NetworkOpt represents a network config in swarm mode.
type NetworkOpt struct {
options []NetworkAttachmentOpts
}

// Set networkopts value
func (n *NetworkOpt) Set(value string) error {
longSyntax, err := regexp.MatchString(`\w+=\w+(,\w+=\w+)*`, value)
if err != nil {
return err
}

var netOpt NetworkAttachmentOpts
if longSyntax {
csvReader := csv.NewReader(strings.NewReader(value))
fields, err := csvReader.Read()
if err != nil {
return err
}

netOpt.Aliases = []string{}
for _, field := range fields {
parts := strings.SplitN(field, "=", 2)

if len(parts) < 2 {
return fmt.Errorf("invalid field %s", field)
}

key := strings.TrimSpace(strings.ToLower(parts[0]))
value := strings.TrimSpace(strings.ToLower(parts[1]))

switch key {
case networkOptName:
netOpt.Target = value
case networkOptAlias:
netOpt.Aliases = append(netOpt.Aliases, value)
case driverOpt:
key, value, err = parseDriverOpt(value)
if err == nil {
if netOpt.DriverOpts == nil {
netOpt.DriverOpts = make(map[string]string)
}
netOpt.DriverOpts[key] = value
} else {
return err
}
default:
return fmt.Errorf("invalid field key %s", key)
}
}
if len(netOpt.Target) == 0 {
return fmt.Errorf("network name/id is not specified")
}
} else {
netOpt.Target = value
}
n.options = append(n.options, netOpt)
return nil
}

// Type returns the type of this option
func (n *NetworkOpt) Type() string {
return "network"
}

// Value returns the networkopts
func (n *NetworkOpt) Value() []NetworkAttachmentOpts {
return n.options
}

// String returns the network opts as a string
func (n *NetworkOpt) String() string {
return ""
}

func parseDriverOpt(driverOpt string) (key string, value string, err error) {
parts := strings.SplitN(driverOpt, "=", 2)
if len(parts) != 2 {
err = fmt.Errorf("invalid key value pair format in driver options")
}
key = strings.TrimSpace(strings.ToLower(parts[0]))
value = strings.TrimSpace(strings.ToLower(parts[1]))
return
}
100 changes: 100 additions & 0 deletions opts/network_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package opts

import (
"testing"

"github.com/docker/docker/pkg/testutil"
"github.com/stretchr/testify/assert"
)

func TestNetworkOptLegacySyntax(t *testing.T) {
testCases := []struct {
value string
expected []NetworkAttachmentOpts
}{
{
value: "docknet1",
expected: []NetworkAttachmentOpts{
{
Target: "docknet1",
},
},
},
}
for _, tc := range testCases {
var network NetworkOpt
assert.NoError(t, network.Set(tc.value))
assert.Equal(t, tc.expected, network.Value())
}
}

func TestNetworkOptCompleteSyntax(t *testing.T) {
testCases := []struct {
value string
expected []NetworkAttachmentOpts
}{
{
value: "name=docknet1,alias=web,driver-opt=field1=value1",
expected: []NetworkAttachmentOpts{
{
Target: "docknet1",
Aliases: []string{"web"},
DriverOpts: map[string]string{
"field1": "value1",
},
},
},
},
{
value: "name=docknet1,alias=web1,alias=web2,driver-opt=field1=value1,driver-opt=field2=value2",
expected: []NetworkAttachmentOpts{
{
Target: "docknet1",
Aliases: []string{"web1", "web2"},
DriverOpts: map[string]string{
"field1": "value1",
"field2": "value2",
},
},
},
},
{
value: "name=docknet1",
expected: []NetworkAttachmentOpts{
{
Target: "docknet1",
Aliases: []string{},
},
},
},
}
for _, tc := range testCases {
var network NetworkOpt
assert.NoError(t, network.Set(tc.value))
assert.Equal(t, tc.expected, network.Value())
}
}

func TestNetworkOptInvalidSyntax(t *testing.T) {
testCases := []struct {
value string
expectedError string
}{
{
value: "invalidField=docknet1",
expectedError: "invalid field",
},
{
value: "network=docknet1,invalid=web",
expectedError: "invalid field",
},
{
value: "driver-opt=field1=value1,driver-opt=field2=value2",
expectedError: "network name/id is not specified",
},
}
for _, tc := range testCases {
var network NetworkOpt
testutil.ErrorContains(t, network.Set(tc.value), tc.expectedError)
}
}
4 changes: 2 additions & 2 deletions vendor.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ github.com/agl/ed25519 d2b94fd789ea21d12fac1a4443dd3a3f79cda72c
github.com/coreos/etcd 824277cb3a577a0e8c829ca9ec557b973fe06d20
github.com/davecgh/go-spew 346938d642f2ec3594ed81d874461961cd0faa76
github.com/docker/distribution b38e5838b7b2f2ad48e06ec4b500011976080621
github.com/docker/docker 4874e05f7452d7d9c60db50296d04c802ce76ae1
github.com/docker/docker 45c6f4262a865a03adaac291a9ce33c0f2190d77
github.com/docker/docker-credential-helpers v0.5.0
github.com/docker/go d30aec9fd63c35133f8f79c3412ad91a3b08be06
github.com/docker/go-connections e15c02316c12de00874640cd76311849de2aeed5
Expand All @@ -15,7 +15,7 @@ github.com/docker/go-units 9e638d38cf6977a37a8ea0078f3ee75a7cdb2dd1
github.com/docker/libnetwork b13e0604016a4944025aaff521d9c125850b0d04
github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
github.com/docker/notary v0.4.2
github.com/docker/swarmkit 998a47fb9c2b727c8a48d372309af0b3032051e2
github.com/docker/swarmkit 1a3e510517be82d18ac04380b5f71eddf06c2fc0
github.com/flynn-archive/go-shlex 3f9db97f856818214da2e1057f8ad84803971cff
github.com/gogo/protobuf 7efa791bd276fd4db00867cbd982b552627c24cb
github.com/golang/protobuf 8ee79997227bf9b34611aee7946ae64735e6fd93
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions vendor/github.com/docker/docker/pkg/term/tc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 0 additions & 51 deletions vendor/github.com/docker/docker/pkg/term/tc_linux_cgo.go

This file was deleted.

Loading