github.com/ali-iotechsys/cli@v20.10.0+incompatible/cli/compose/schema/schema_test.go (about) 1 package schema 2 3 import ( 4 "fmt" 5 "testing" 6 7 "gotest.tools/v3/assert" 8 ) 9 10 type dict map[string]interface{} 11 12 func TestValidate(t *testing.T) { 13 config := dict{ 14 "version": "3.0", 15 "services": dict{ 16 "foo": dict{ 17 "image": "busybox", 18 }, 19 }, 20 } 21 22 assert.NilError(t, Validate(config, "3.0")) 23 } 24 25 func TestValidateUndefinedTopLevelOption(t *testing.T) { 26 config := dict{ 27 "version": "3.0", 28 "helicopters": dict{ 29 "foo": dict{ 30 "image": "busybox", 31 }, 32 }, 33 } 34 35 err := Validate(config, "3.0") 36 assert.ErrorContains(t, err, "Additional property helicopters is not allowed") 37 } 38 39 func TestValidateAllowsXTopLevelFields(t *testing.T) { 40 config := dict{ 41 "version": "3.4", 42 "x-extra-stuff": dict{}, 43 } 44 45 err := Validate(config, "3.4") 46 assert.NilError(t, err) 47 } 48 49 func TestValidateAllowsXFields(t *testing.T) { 50 config := dict{ 51 "version": "3.7", 52 "services": dict{ 53 "bar": dict{ 54 "x-extra-stuff": dict{}, 55 }, 56 }, 57 "volumes": dict{ 58 "bar": dict{ 59 "x-extra-stuff": dict{}, 60 }, 61 }, 62 "networks": dict{ 63 "bar": dict{ 64 "x-extra-stuff": dict{}, 65 }, 66 }, 67 "configs": dict{ 68 "bar": dict{ 69 "x-extra-stuff": dict{}, 70 }, 71 }, 72 "secrets": dict{ 73 "bar": dict{ 74 "x-extra-stuff": dict{}, 75 }, 76 }, 77 } 78 err := Validate(config, "3.7") 79 assert.NilError(t, err) 80 } 81 82 func TestValidateCredentialSpecs(t *testing.T) { 83 tests := []struct { 84 version string 85 expectedErr string 86 }{ 87 {version: "3.0", expectedErr: "credential_spec"}, 88 {version: "3.1", expectedErr: "credential_spec"}, 89 {version: "3.2", expectedErr: "credential_spec"}, 90 {version: "3.3", expectedErr: "config"}, 91 {version: "3.4", expectedErr: "config"}, 92 {version: "3.5", expectedErr: "config"}, 93 {version: "3.6", expectedErr: "config"}, 94 {version: "3.7", expectedErr: "config"}, 95 {version: "3.8"}, 96 {version: "3.9"}, 97 } 98 99 for _, tc := range tests { 100 tc := tc 101 t.Run(tc.version, func(t *testing.T) { 102 config := dict{ 103 "version": "99.99", 104 "services": dict{ 105 "foo": dict{ 106 "image": "busybox", 107 "credential_spec": dict{ 108 "config": "foobar", 109 }, 110 }, 111 }, 112 } 113 err := Validate(config, tc.version) 114 if tc.expectedErr != "" { 115 assert.ErrorContains(t, err, fmt.Sprintf("Additional property %s is not allowed", tc.expectedErr)) 116 } else { 117 assert.NilError(t, err) 118 } 119 }) 120 } 121 } 122 123 func TestValidateSecretConfigNames(t *testing.T) { 124 config := dict{ 125 "version": "3.5", 126 "configs": dict{ 127 "bar": dict{ 128 "name": "foobar", 129 }, 130 }, 131 "secrets": dict{ 132 "baz": dict{ 133 "name": "foobaz", 134 }, 135 }, 136 } 137 138 err := Validate(config, "3.5") 139 assert.NilError(t, err) 140 } 141 142 func TestValidateInvalidVersion(t *testing.T) { 143 config := dict{ 144 "version": "2.1", 145 "services": dict{ 146 "foo": dict{ 147 "image": "busybox", 148 }, 149 }, 150 } 151 152 err := Validate(config, "2.1") 153 assert.ErrorContains(t, err, "unsupported Compose file version: 2.1") 154 } 155 156 type array []interface{} 157 158 func TestValidatePlacement(t *testing.T) { 159 config := dict{ 160 "version": "3.3", 161 "services": dict{ 162 "foo": dict{ 163 "image": "busybox", 164 "deploy": dict{ 165 "placement": dict{ 166 "preferences": array{ 167 dict{ 168 "spread": "node.labels.az", 169 }, 170 }, 171 }, 172 }, 173 }, 174 }, 175 } 176 177 assert.NilError(t, Validate(config, "3.3")) 178 } 179 180 func TestValidateIsolation(t *testing.T) { 181 config := dict{ 182 "version": "3.5", 183 "services": dict{ 184 "foo": dict{ 185 "image": "busybox", 186 "isolation": "some-isolation-value", 187 }, 188 }, 189 } 190 assert.NilError(t, Validate(config, "3.5")) 191 } 192 193 func TestValidateRollbackConfig(t *testing.T) { 194 config := dict{ 195 "version": "3.4", 196 "services": dict{ 197 "foo": dict{ 198 "image": "busybox", 199 "deploy": dict{ 200 "rollback_config": dict{ 201 "parallelism": 1, 202 }, 203 }, 204 }, 205 }, 206 } 207 208 assert.NilError(t, Validate(config, "3.7")) 209 } 210 211 func TestValidateRollbackConfigWithOrder(t *testing.T) { 212 config := dict{ 213 "version": "3.4", 214 "services": dict{ 215 "foo": dict{ 216 "image": "busybox", 217 "deploy": dict{ 218 "rollback_config": dict{ 219 "parallelism": 1, 220 "order": "start-first", 221 }, 222 }, 223 }, 224 }, 225 } 226 227 assert.NilError(t, Validate(config, "3.7")) 228 } 229 230 func TestValidateRollbackConfigWithUpdateConfig(t *testing.T) { 231 config := dict{ 232 "version": "3.4", 233 "services": dict{ 234 "foo": dict{ 235 "image": "busybox", 236 "deploy": dict{ 237 "update_config": dict{ 238 "parallelism": 1, 239 "order": "start-first", 240 }, 241 "rollback_config": dict{ 242 "parallelism": 1, 243 "order": "start-first", 244 }, 245 }, 246 }, 247 }, 248 } 249 250 assert.NilError(t, Validate(config, "3.7")) 251 } 252 253 func TestValidateRollbackConfigWithUpdateConfigFull(t *testing.T) { 254 config := dict{ 255 "version": "3.4", 256 "services": dict{ 257 "foo": dict{ 258 "image": "busybox", 259 "deploy": dict{ 260 "update_config": dict{ 261 "parallelism": 1, 262 "order": "start-first", 263 "delay": "10s", 264 "failure_action": "pause", 265 "monitor": "10s", 266 }, 267 "rollback_config": dict{ 268 "parallelism": 1, 269 "order": "start-first", 270 "delay": "10s", 271 "failure_action": "pause", 272 "monitor": "10s", 273 }, 274 }, 275 }, 276 }, 277 } 278 279 assert.NilError(t, Validate(config, "3.7")) 280 }