github.com/zhouyu0/docker-note@v0.0.0-20190722021225-b8d3825084db/daemon/cluster/convert/container.go (about) 1 package convert // import "github.com/docker/docker/daemon/cluster/convert" 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 8 "github.com/docker/docker/api/types/container" 9 mounttypes "github.com/docker/docker/api/types/mount" 10 types "github.com/docker/docker/api/types/swarm" 11 swarmapi "github.com/docker/swarmkit/api" 12 gogotypes "github.com/gogo/protobuf/types" 13 "github.com/sirupsen/logrus" 14 ) 15 16 func containerSpecFromGRPC(c *swarmapi.ContainerSpec) *types.ContainerSpec { 17 if c == nil { 18 return nil 19 } 20 containerSpec := &types.ContainerSpec{ 21 Image: c.Image, 22 Labels: c.Labels, 23 Command: c.Command, 24 Args: c.Args, 25 Hostname: c.Hostname, 26 Env: c.Env, 27 Dir: c.Dir, 28 User: c.User, 29 Groups: c.Groups, 30 StopSignal: c.StopSignal, 31 TTY: c.TTY, 32 OpenStdin: c.OpenStdin, 33 ReadOnly: c.ReadOnly, 34 Hosts: c.Hosts, 35 Secrets: secretReferencesFromGRPC(c.Secrets), 36 Configs: configReferencesFromGRPC(c.Configs), 37 Isolation: IsolationFromGRPC(c.Isolation), 38 Init: initFromGRPC(c.Init), 39 } 40 41 if c.DNSConfig != nil { 42 containerSpec.DNSConfig = &types.DNSConfig{ 43 Nameservers: c.DNSConfig.Nameservers, 44 Search: c.DNSConfig.Search, 45 Options: c.DNSConfig.Options, 46 } 47 } 48 49 // Privileges 50 if c.Privileges != nil { 51 containerSpec.Privileges = &types.Privileges{} 52 53 if c.Privileges.CredentialSpec != nil { 54 containerSpec.Privileges.CredentialSpec = &types.CredentialSpec{} 55 switch c.Privileges.CredentialSpec.Source.(type) { 56 case *swarmapi.Privileges_CredentialSpec_File: 57 containerSpec.Privileges.CredentialSpec.File = c.Privileges.CredentialSpec.GetFile() 58 case *swarmapi.Privileges_CredentialSpec_Registry: 59 containerSpec.Privileges.CredentialSpec.Registry = c.Privileges.CredentialSpec.GetRegistry() 60 } 61 } 62 63 if c.Privileges.SELinuxContext != nil { 64 containerSpec.Privileges.SELinuxContext = &types.SELinuxContext{ 65 Disable: c.Privileges.SELinuxContext.Disable, 66 User: c.Privileges.SELinuxContext.User, 67 Type: c.Privileges.SELinuxContext.Type, 68 Role: c.Privileges.SELinuxContext.Role, 69 Level: c.Privileges.SELinuxContext.Level, 70 } 71 } 72 } 73 74 // Mounts 75 for _, m := range c.Mounts { 76 mount := mounttypes.Mount{ 77 Target: m.Target, 78 Source: m.Source, 79 Type: mounttypes.Type(strings.ToLower(swarmapi.Mount_MountType_name[int32(m.Type)])), 80 ReadOnly: m.ReadOnly, 81 } 82 83 if m.BindOptions != nil { 84 mount.BindOptions = &mounttypes.BindOptions{ 85 Propagation: mounttypes.Propagation(strings.ToLower(swarmapi.Mount_BindOptions_MountPropagation_name[int32(m.BindOptions.Propagation)])), 86 } 87 } 88 89 if m.VolumeOptions != nil { 90 mount.VolumeOptions = &mounttypes.VolumeOptions{ 91 NoCopy: m.VolumeOptions.NoCopy, 92 Labels: m.VolumeOptions.Labels, 93 } 94 if m.VolumeOptions.DriverConfig != nil { 95 mount.VolumeOptions.DriverConfig = &mounttypes.Driver{ 96 Name: m.VolumeOptions.DriverConfig.Name, 97 Options: m.VolumeOptions.DriverConfig.Options, 98 } 99 } 100 } 101 102 if m.TmpfsOptions != nil { 103 mount.TmpfsOptions = &mounttypes.TmpfsOptions{ 104 SizeBytes: m.TmpfsOptions.SizeBytes, 105 Mode: m.TmpfsOptions.Mode, 106 } 107 } 108 containerSpec.Mounts = append(containerSpec.Mounts, mount) 109 } 110 111 if c.StopGracePeriod != nil { 112 grace, _ := gogotypes.DurationFromProto(c.StopGracePeriod) 113 containerSpec.StopGracePeriod = &grace 114 } 115 116 if c.Healthcheck != nil { 117 containerSpec.Healthcheck = healthConfigFromGRPC(c.Healthcheck) 118 } 119 120 return containerSpec 121 } 122 123 func initFromGRPC(v *gogotypes.BoolValue) *bool { 124 if v == nil { 125 return nil 126 } 127 value := v.GetValue() 128 return &value 129 } 130 131 func initToGRPC(v *bool) *gogotypes.BoolValue { 132 if v == nil { 133 return nil 134 } 135 return &gogotypes.BoolValue{Value: *v} 136 } 137 138 func secretReferencesToGRPC(sr []*types.SecretReference) []*swarmapi.SecretReference { 139 refs := make([]*swarmapi.SecretReference, 0, len(sr)) 140 for _, s := range sr { 141 ref := &swarmapi.SecretReference{ 142 SecretID: s.SecretID, 143 SecretName: s.SecretName, 144 } 145 if s.File != nil { 146 ref.Target = &swarmapi.SecretReference_File{ 147 File: &swarmapi.FileTarget{ 148 Name: s.File.Name, 149 UID: s.File.UID, 150 GID: s.File.GID, 151 Mode: s.File.Mode, 152 }, 153 } 154 } 155 156 refs = append(refs, ref) 157 } 158 159 return refs 160 } 161 162 func secretReferencesFromGRPC(sr []*swarmapi.SecretReference) []*types.SecretReference { 163 refs := make([]*types.SecretReference, 0, len(sr)) 164 for _, s := range sr { 165 target := s.GetFile() 166 if target == nil { 167 // not a file target 168 logrus.Warnf("secret target not a file: secret=%s", s.SecretID) 169 continue 170 } 171 refs = append(refs, &types.SecretReference{ 172 File: &types.SecretReferenceFileTarget{ 173 Name: target.Name, 174 UID: target.UID, 175 GID: target.GID, 176 Mode: target.Mode, 177 }, 178 SecretID: s.SecretID, 179 SecretName: s.SecretName, 180 }) 181 } 182 183 return refs 184 } 185 186 func configReferencesToGRPC(sr []*types.ConfigReference) []*swarmapi.ConfigReference { 187 refs := make([]*swarmapi.ConfigReference, 0, len(sr)) 188 for _, s := range sr { 189 ref := &swarmapi.ConfigReference{ 190 ConfigID: s.ConfigID, 191 ConfigName: s.ConfigName, 192 } 193 if s.File != nil { 194 ref.Target = &swarmapi.ConfigReference_File{ 195 File: &swarmapi.FileTarget{ 196 Name: s.File.Name, 197 UID: s.File.UID, 198 GID: s.File.GID, 199 Mode: s.File.Mode, 200 }, 201 } 202 } 203 204 refs = append(refs, ref) 205 } 206 207 return refs 208 } 209 210 func configReferencesFromGRPC(sr []*swarmapi.ConfigReference) []*types.ConfigReference { 211 refs := make([]*types.ConfigReference, 0, len(sr)) 212 for _, s := range sr { 213 target := s.GetFile() 214 if target == nil { 215 // not a file target 216 logrus.Warnf("config target not a file: config=%s", s.ConfigID) 217 continue 218 } 219 refs = append(refs, &types.ConfigReference{ 220 File: &types.ConfigReferenceFileTarget{ 221 Name: target.Name, 222 UID: target.UID, 223 GID: target.GID, 224 Mode: target.Mode, 225 }, 226 ConfigID: s.ConfigID, 227 ConfigName: s.ConfigName, 228 }) 229 } 230 231 return refs 232 } 233 234 func containerToGRPC(c *types.ContainerSpec) (*swarmapi.ContainerSpec, error) { 235 containerSpec := &swarmapi.ContainerSpec{ 236 Image: c.Image, 237 Labels: c.Labels, 238 Command: c.Command, 239 Args: c.Args, 240 Hostname: c.Hostname, 241 Env: c.Env, 242 Dir: c.Dir, 243 User: c.User, 244 Groups: c.Groups, 245 StopSignal: c.StopSignal, 246 TTY: c.TTY, 247 OpenStdin: c.OpenStdin, 248 ReadOnly: c.ReadOnly, 249 Hosts: c.Hosts, 250 Secrets: secretReferencesToGRPC(c.Secrets), 251 Configs: configReferencesToGRPC(c.Configs), 252 Isolation: isolationToGRPC(c.Isolation), 253 Init: initToGRPC(c.Init), 254 } 255 256 if c.DNSConfig != nil { 257 containerSpec.DNSConfig = &swarmapi.ContainerSpec_DNSConfig{ 258 Nameservers: c.DNSConfig.Nameservers, 259 Search: c.DNSConfig.Search, 260 Options: c.DNSConfig.Options, 261 } 262 } 263 264 if c.StopGracePeriod != nil { 265 containerSpec.StopGracePeriod = gogotypes.DurationProto(*c.StopGracePeriod) 266 } 267 268 // Privileges 269 if c.Privileges != nil { 270 containerSpec.Privileges = &swarmapi.Privileges{} 271 272 if c.Privileges.CredentialSpec != nil { 273 containerSpec.Privileges.CredentialSpec = &swarmapi.Privileges_CredentialSpec{} 274 275 if c.Privileges.CredentialSpec.File != "" && c.Privileges.CredentialSpec.Registry != "" { 276 return nil, errors.New("cannot specify both \"file\" and \"registry\" credential specs") 277 } 278 if c.Privileges.CredentialSpec.File != "" { 279 containerSpec.Privileges.CredentialSpec.Source = &swarmapi.Privileges_CredentialSpec_File{ 280 File: c.Privileges.CredentialSpec.File, 281 } 282 } else if c.Privileges.CredentialSpec.Registry != "" { 283 containerSpec.Privileges.CredentialSpec.Source = &swarmapi.Privileges_CredentialSpec_Registry{ 284 Registry: c.Privileges.CredentialSpec.Registry, 285 } 286 } else { 287 return nil, errors.New("must either provide \"file\" or \"registry\" for credential spec") 288 } 289 } 290 291 if c.Privileges.SELinuxContext != nil { 292 containerSpec.Privileges.SELinuxContext = &swarmapi.Privileges_SELinuxContext{ 293 Disable: c.Privileges.SELinuxContext.Disable, 294 User: c.Privileges.SELinuxContext.User, 295 Type: c.Privileges.SELinuxContext.Type, 296 Role: c.Privileges.SELinuxContext.Role, 297 Level: c.Privileges.SELinuxContext.Level, 298 } 299 } 300 } 301 302 // Mounts 303 for _, m := range c.Mounts { 304 mount := swarmapi.Mount{ 305 Target: m.Target, 306 Source: m.Source, 307 ReadOnly: m.ReadOnly, 308 } 309 310 if mountType, ok := swarmapi.Mount_MountType_value[strings.ToUpper(string(m.Type))]; ok { 311 mount.Type = swarmapi.Mount_MountType(mountType) 312 } else if string(m.Type) != "" { 313 return nil, fmt.Errorf("invalid MountType: %q", m.Type) 314 } 315 316 if m.BindOptions != nil { 317 if mountPropagation, ok := swarmapi.Mount_BindOptions_MountPropagation_value[strings.ToUpper(string(m.BindOptions.Propagation))]; ok { 318 mount.BindOptions = &swarmapi.Mount_BindOptions{Propagation: swarmapi.Mount_BindOptions_MountPropagation(mountPropagation)} 319 } else if string(m.BindOptions.Propagation) != "" { 320 return nil, fmt.Errorf("invalid MountPropagation: %q", m.BindOptions.Propagation) 321 } 322 } 323 324 if m.VolumeOptions != nil { 325 mount.VolumeOptions = &swarmapi.Mount_VolumeOptions{ 326 NoCopy: m.VolumeOptions.NoCopy, 327 Labels: m.VolumeOptions.Labels, 328 } 329 if m.VolumeOptions.DriverConfig != nil { 330 mount.VolumeOptions.DriverConfig = &swarmapi.Driver{ 331 Name: m.VolumeOptions.DriverConfig.Name, 332 Options: m.VolumeOptions.DriverConfig.Options, 333 } 334 } 335 } 336 337 if m.TmpfsOptions != nil { 338 mount.TmpfsOptions = &swarmapi.Mount_TmpfsOptions{ 339 SizeBytes: m.TmpfsOptions.SizeBytes, 340 Mode: m.TmpfsOptions.Mode, 341 } 342 } 343 344 containerSpec.Mounts = append(containerSpec.Mounts, mount) 345 } 346 347 if c.Healthcheck != nil { 348 containerSpec.Healthcheck = healthConfigToGRPC(c.Healthcheck) 349 } 350 351 return containerSpec, nil 352 } 353 354 func healthConfigFromGRPC(h *swarmapi.HealthConfig) *container.HealthConfig { 355 interval, _ := gogotypes.DurationFromProto(h.Interval) 356 timeout, _ := gogotypes.DurationFromProto(h.Timeout) 357 startPeriod, _ := gogotypes.DurationFromProto(h.StartPeriod) 358 return &container.HealthConfig{ 359 Test: h.Test, 360 Interval: interval, 361 Timeout: timeout, 362 Retries: int(h.Retries), 363 StartPeriod: startPeriod, 364 } 365 } 366 367 func healthConfigToGRPC(h *container.HealthConfig) *swarmapi.HealthConfig { 368 return &swarmapi.HealthConfig{ 369 Test: h.Test, 370 Interval: gogotypes.DurationProto(h.Interval), 371 Timeout: gogotypes.DurationProto(h.Timeout), 372 Retries: int32(h.Retries), 373 StartPeriod: gogotypes.DurationProto(h.StartPeriod), 374 } 375 } 376 377 // IsolationFromGRPC converts a swarm api container isolation to a moby isolation representation 378 func IsolationFromGRPC(i swarmapi.ContainerSpec_Isolation) container.Isolation { 379 switch i { 380 case swarmapi.ContainerIsolationHyperV: 381 return container.IsolationHyperV 382 case swarmapi.ContainerIsolationProcess: 383 return container.IsolationProcess 384 case swarmapi.ContainerIsolationDefault: 385 return container.IsolationDefault 386 } 387 return container.IsolationEmpty 388 } 389 390 func isolationToGRPC(i container.Isolation) swarmapi.ContainerSpec_Isolation { 391 if i.IsHyperV() { 392 return swarmapi.ContainerIsolationHyperV 393 } 394 if i.IsProcess() { 395 return swarmapi.ContainerIsolationProcess 396 } 397 return swarmapi.ContainerIsolationDefault 398 }