Signed-off-by: Daniel Nephin <dnephin@docker.com>
| ... | ... |
@@ -40,12 +40,12 @@ func AddStackLabel(namespace Namespace, labels map[string]string) map[string]str |
| 40 | 40 |
return labels |
| 41 | 41 |
} |
| 42 | 42 |
|
| 43 |
-type networks map[string]composetypes.NetworkConfig |
|
| 43 |
+type networkMap map[string]composetypes.NetworkConfig |
|
| 44 | 44 |
|
| 45 | 45 |
// ConvertNetworks from the compose-file type to the engine API type |
| 46 | 46 |
func ConvertNetworks( |
| 47 | 47 |
namespace Namespace, |
| 48 |
- networks networks, |
|
| 48 |
+ networks networkMap, |
|
| 49 | 49 |
servicesNetworks map[string]struct{},
|
| 50 | 50 |
) (map[string]types.NetworkCreate, []string) {
|
| 51 | 51 |
if networks == nil {
|
| ... | ... |
@@ -28,7 +28,7 @@ func TestAddStackLabel(t *testing.T) {
|
| 28 | 28 |
|
| 29 | 29 |
func TestConvertNetworks(t *testing.T) {
|
| 30 | 30 |
namespace := Namespace{name: "foo"}
|
| 31 |
- source := networks{
|
|
| 31 |
+ source := networkMap{
|
|
| 32 | 32 |
"normal": composetypes.NetworkConfig{
|
| 33 | 33 |
Driver: "overlay", |
| 34 | 34 |
DriverOpts: map[string]string{
|
| ... | ... |
@@ -127,7 +127,7 @@ func convertService( |
| 127 | 127 |
|
| 128 | 128 |
func convertServiceNetworks( |
| 129 | 129 |
networks map[string]*composetypes.ServiceNetworkConfig, |
| 130 |
- networkConfigs networks, |
|
| 130 |
+ networkConfigs networkMap, |
|
| 131 | 131 |
namespace Namespace, |
| 132 | 132 |
name string, |
| 133 | 133 |
) ([]swarm.NetworkAttachmentConfig, error) {
|
| ... | ... |
@@ -144,7 +144,8 @@ func convertServiceNetworks( |
| 144 | 144 |
for networkName, network := range networks {
|
| 145 | 145 |
networkConfig, ok := networkConfigs[networkName] |
| 146 | 146 |
if !ok {
|
| 147 |
- return []swarm.NetworkAttachmentConfig{}, fmt.Errorf("invalid network: %s", networkName)
|
|
| 147 |
+ return []swarm.NetworkAttachmentConfig{}, fmt.Errorf(
|
|
| 148 |
+ "service %q references network %q, which is not declared", name, networkName) |
|
| 148 | 149 |
} |
| 149 | 150 |
var aliases []string |
| 150 | 151 |
if network != nil {
|
| ... | ... |
@@ -181,7 +182,7 @@ func convertHealthcheck(healthcheck *composetypes.HealthCheckConfig) (*container |
| 181 | 181 |
) |
| 182 | 182 |
if healthcheck.Disable {
|
| 183 | 183 |
if len(healthcheck.Test) != 0 {
|
| 184 |
- return nil, fmt.Errorf("command and disable key can't be set at the same time")
|
|
| 184 |
+ return nil, fmt.Errorf("test and disable can't be set at the same time")
|
|
| 185 | 185 |
} |
| 186 | 186 |
return &container.HealthConfig{
|
| 187 | 187 |
Test: []string{"NONE"},
|
| ... | ... |
@@ -1,17 +1,21 @@ |
| 1 | 1 |
package composetransform |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "sort" |
|
| 5 |
+ "strings" |
|
| 4 | 6 |
"testing" |
| 7 |
+ "time" |
|
| 5 | 8 |
|
| 9 |
+ composetypes "github.com/aanand/compose-file/types" |
|
| 10 |
+ "github.com/docker/docker/api/types/container" |
|
| 6 | 11 |
"github.com/docker/docker/api/types/swarm" |
| 7 | 12 |
"github.com/docker/docker/pkg/testutil/assert" |
| 8 | 13 |
) |
| 9 | 14 |
|
| 10 | 15 |
func TestConvertRestartPolicyFromNone(t *testing.T) {
|
| 11 | 16 |
policy, err := convertRestartPolicy("no", nil)
|
| 12 |
- var expected *swarm.RestartPolicy |
|
| 13 | 17 |
assert.NilError(t, err) |
| 14 |
- assert.Equal(t, policy, expected) |
|
| 18 |
+ assert.Equal(t, policy, (*swarm.RestartPolicy)(nil)) |
|
| 15 | 19 |
} |
| 16 | 20 |
|
| 17 | 21 |
func TestConvertRestartPolicyFromUnknown(t *testing.T) {
|
| ... | ... |
@@ -38,3 +42,152 @@ func TestConvertRestartPolicyFromFailure(t *testing.T) {
|
| 38 | 38 |
assert.NilError(t, err) |
| 39 | 39 |
assert.DeepEqual(t, policy, expected) |
| 40 | 40 |
} |
| 41 |
+ |
|
| 42 |
+func TestConvertEnvironment(t *testing.T) {
|
|
| 43 |
+ source := map[string]string{
|
|
| 44 |
+ "foo": "bar", |
|
| 45 |
+ "key": "value", |
|
| 46 |
+ } |
|
| 47 |
+ env := convertEnvironment(source) |
|
| 48 |
+ sort.Strings(env) |
|
| 49 |
+ assert.DeepEqual(t, env, []string{"foo=bar", "key=value"})
|
|
| 50 |
+} |
|
| 51 |
+ |
|
| 52 |
+func TestConvertResourcesFull(t *testing.T) {
|
|
| 53 |
+ source := composetypes.Resources{
|
|
| 54 |
+ Limits: &composetypes.Resource{
|
|
| 55 |
+ NanoCPUs: "0.003", |
|
| 56 |
+ MemoryBytes: composetypes.UnitBytes(300000000), |
|
| 57 |
+ }, |
|
| 58 |
+ Reservations: &composetypes.Resource{
|
|
| 59 |
+ NanoCPUs: "0.002", |
|
| 60 |
+ MemoryBytes: composetypes.UnitBytes(200000000), |
|
| 61 |
+ }, |
|
| 62 |
+ } |
|
| 63 |
+ resources, err := convertResources(source) |
|
| 64 |
+ assert.NilError(t, err) |
|
| 65 |
+ |
|
| 66 |
+ expected := &swarm.ResourceRequirements{
|
|
| 67 |
+ Limits: &swarm.Resources{
|
|
| 68 |
+ NanoCPUs: 3000000, |
|
| 69 |
+ MemoryBytes: 300000000, |
|
| 70 |
+ }, |
|
| 71 |
+ Reservations: &swarm.Resources{
|
|
| 72 |
+ NanoCPUs: 2000000, |
|
| 73 |
+ MemoryBytes: 200000000, |
|
| 74 |
+ }, |
|
| 75 |
+ } |
|
| 76 |
+ assert.DeepEqual(t, resources, expected) |
|
| 77 |
+} |
|
| 78 |
+ |
|
| 79 |
+func TestConvertHealthcheck(t *testing.T) {
|
|
| 80 |
+ retries := uint64(10) |
|
| 81 |
+ source := &composetypes.HealthCheckConfig{
|
|
| 82 |
+ Test: []string{"EXEC", "touch", "/foo"},
|
|
| 83 |
+ Timeout: "30s", |
|
| 84 |
+ Interval: "2ms", |
|
| 85 |
+ Retries: &retries, |
|
| 86 |
+ } |
|
| 87 |
+ expected := &container.HealthConfig{
|
|
| 88 |
+ Test: source.Test, |
|
| 89 |
+ Timeout: 30 * time.Second, |
|
| 90 |
+ Interval: 2 * time.Millisecond, |
|
| 91 |
+ Retries: 10, |
|
| 92 |
+ } |
|
| 93 |
+ |
|
| 94 |
+ healthcheck, err := convertHealthcheck(source) |
|
| 95 |
+ assert.NilError(t, err) |
|
| 96 |
+ assert.DeepEqual(t, healthcheck, expected) |
|
| 97 |
+} |
|
| 98 |
+ |
|
| 99 |
+func TestConvertHealthcheckDisable(t *testing.T) {
|
|
| 100 |
+ source := &composetypes.HealthCheckConfig{Disable: true}
|
|
| 101 |
+ expected := &container.HealthConfig{
|
|
| 102 |
+ Test: []string{"NONE"},
|
|
| 103 |
+ } |
|
| 104 |
+ |
|
| 105 |
+ healthcheck, err := convertHealthcheck(source) |
|
| 106 |
+ assert.NilError(t, err) |
|
| 107 |
+ assert.DeepEqual(t, healthcheck, expected) |
|
| 108 |
+} |
|
| 109 |
+ |
|
| 110 |
+func TestConvertHealthcheckDisableWithTest(t *testing.T) {
|
|
| 111 |
+ source := &composetypes.HealthCheckConfig{
|
|
| 112 |
+ Disable: true, |
|
| 113 |
+ Test: []string{"EXEC", "touch"},
|
|
| 114 |
+ } |
|
| 115 |
+ _, err := convertHealthcheck(source) |
|
| 116 |
+ assert.Error(t, err, "test and disable can't be set") |
|
| 117 |
+} |
|
| 118 |
+ |
|
| 119 |
+func TestConvertServiceNetworksOnlyDefault(t *testing.T) {
|
|
| 120 |
+ networkConfigs := networkMap{}
|
|
| 121 |
+ networks := map[string]*composetypes.ServiceNetworkConfig{}
|
|
| 122 |
+ |
|
| 123 |
+ configs, err := convertServiceNetworks( |
|
| 124 |
+ networks, networkConfigs, NewNamespace("foo"), "service")
|
|
| 125 |
+ |
|
| 126 |
+ expected := []swarm.NetworkAttachmentConfig{
|
|
| 127 |
+ {
|
|
| 128 |
+ Target: "foo_default", |
|
| 129 |
+ Aliases: []string{"service"},
|
|
| 130 |
+ }, |
|
| 131 |
+ } |
|
| 132 |
+ |
|
| 133 |
+ assert.NilError(t, err) |
|
| 134 |
+ assert.DeepEqual(t, configs, expected) |
|
| 135 |
+} |
|
| 136 |
+ |
|
| 137 |
+func TestConvertServiceNetworks(t *testing.T) {
|
|
| 138 |
+ networkConfigs := networkMap{
|
|
| 139 |
+ "front": composetypes.NetworkConfig{
|
|
| 140 |
+ External: composetypes.External{
|
|
| 141 |
+ External: true, |
|
| 142 |
+ Name: "fronttier", |
|
| 143 |
+ }, |
|
| 144 |
+ }, |
|
| 145 |
+ "back": composetypes.NetworkConfig{},
|
|
| 146 |
+ } |
|
| 147 |
+ networks := map[string]*composetypes.ServiceNetworkConfig{
|
|
| 148 |
+ "front": {
|
|
| 149 |
+ Aliases: []string{"something"},
|
|
| 150 |
+ }, |
|
| 151 |
+ "back": {
|
|
| 152 |
+ Aliases: []string{"other"},
|
|
| 153 |
+ }, |
|
| 154 |
+ } |
|
| 155 |
+ |
|
| 156 |
+ configs, err := convertServiceNetworks( |
|
| 157 |
+ networks, networkConfigs, NewNamespace("foo"), "service")
|
|
| 158 |
+ |
|
| 159 |
+ expected := []swarm.NetworkAttachmentConfig{
|
|
| 160 |
+ {
|
|
| 161 |
+ Target: "foo_back", |
|
| 162 |
+ Aliases: []string{"other", "service"},
|
|
| 163 |
+ }, |
|
| 164 |
+ {
|
|
| 165 |
+ Target: "fronttier", |
|
| 166 |
+ Aliases: []string{"something", "service"},
|
|
| 167 |
+ }, |
|
| 168 |
+ } |
|
| 169 |
+ |
|
| 170 |
+ sortedConfigs := byTargetSort(configs) |
|
| 171 |
+ sort.Sort(&sortedConfigs) |
|
| 172 |
+ |
|
| 173 |
+ assert.NilError(t, err) |
|
| 174 |
+ assert.DeepEqual(t, []swarm.NetworkAttachmentConfig(sortedConfigs), expected) |
|
| 175 |
+} |
|
| 176 |
+ |
|
| 177 |
+type byTargetSort []swarm.NetworkAttachmentConfig |
|
| 178 |
+ |
|
| 179 |
+func (s byTargetSort) Len() int {
|
|
| 180 |
+ return len(s) |
|
| 181 |
+} |
|
| 182 |
+ |
|
| 183 |
+func (s byTargetSort) Less(i, j int) bool {
|
|
| 184 |
+ return strings.Compare(s[i].Target, s[j].Target) < 0 |
|
| 185 |
+} |
|
| 186 |
+ |
|
| 187 |
+func (s byTargetSort) Swap(i, j int) {
|
|
| 188 |
+ s[i], s[j] = s[j], s[i] |
|
| 189 |
+} |
| ... | ... |
@@ -23,15 +23,15 @@ func TestIsNoCopy(t *testing.T) {
|
| 23 | 23 |
assert.Equal(t, isNoCopy([]string{"foo", "rw"}), false)
|
| 24 | 24 |
} |
| 25 | 25 |
|
| 26 |
-func TesTGetBindOptions(t *testing.T) {
|
|
| 26 |
+func TestGetBindOptions(t *testing.T) {
|
|
| 27 | 27 |
opts := getBindOptions([]string{"slave"})
|
| 28 |
- expected := &mount.BindOptions{Propagation: mount.PropagationSlave}
|
|
| 29 |
- assert.Equal(t, opts, expected) |
|
| 28 |
+ expected := mount.BindOptions{Propagation: mount.PropagationSlave}
|
|
| 29 |
+ assert.Equal(t, *opts, expected) |
|
| 30 | 30 |
} |
| 31 | 31 |
|
| 32 |
-func TesTGetBindOptionsNone(t *testing.T) {
|
|
| 32 |
+func TestGetBindOptionsNone(t *testing.T) {
|
|
| 33 | 33 |
opts := getBindOptions([]string{"ro"})
|
| 34 |
- assert.Equal(t, opts, nil) |
|
| 34 |
+ assert.Equal(t, opts, (*mount.BindOptions)(nil)) |
|
| 35 | 35 |
} |
| 36 | 36 |
|
| 37 | 37 |
func TestConvertVolumeToMountNamedVolume(t *testing.T) {
|