mirror of
https://github.com/docker/compose.git
synced 2025-07-21 12:44:54 +02:00
commit
de4ba33c60
@ -162,41 +162,11 @@ func (cs *aciContainerService) Run(ctx context.Context, r containers.ContainerCo
|
|||||||
return errors.New(fmt.Sprintf("invalid container name. ACI container name cannot include %q", composeContainerSeparator))
|
return errors.New(fmt.Sprintf("invalid container name. ACI container name cannot include %q", composeContainerSeparator))
|
||||||
}
|
}
|
||||||
|
|
||||||
var ports []types.ServicePortConfig
|
project, err := convert.ContainerToComposeProject(r, singleContainerName)
|
||||||
for _, p := range r.Ports {
|
|
||||||
ports = append(ports, types.ServicePortConfig{
|
|
||||||
Target: p.ContainerPort,
|
|
||||||
Published: p.HostPort,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
projectVolumes, serviceConfigVolumes, err := convert.GetRunVolumes(r.Volumes)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
project := types.Project{
|
|
||||||
Name: r.ID,
|
|
||||||
Services: []types.ServiceConfig{
|
|
||||||
{
|
|
||||||
Name: singleContainerName,
|
|
||||||
Image: r.Image,
|
|
||||||
Ports: ports,
|
|
||||||
Labels: r.Labels,
|
|
||||||
Volumes: serviceConfigVolumes,
|
|
||||||
Deploy: &types.DeployConfig{
|
|
||||||
Resources: types.Resources{
|
|
||||||
Limits: &types.Resource{
|
|
||||||
NanoCPUs: fmt.Sprintf("%f", r.CPULimit),
|
|
||||||
MemoryBytes: types.UnitBytes(r.MemLimit.Value()),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Volumes: projectVolumes,
|
|
||||||
}
|
|
||||||
|
|
||||||
logrus.Debugf("Running container %q with name %q\n", r.Image, r.ID)
|
logrus.Debugf("Running container %q with name %q\n", r.Image, r.ID)
|
||||||
groupDefinition, err := convert.ToContainerGroup(cs.ctx, project)
|
groupDefinition, err := convert.ToContainerGroup(cs.ctx, project)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
63
azure/convert/container.go
Normal file
63
azure/convert/container.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package convert
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/compose-spec/compose-go/types"
|
||||||
|
|
||||||
|
"github.com/docker/api/containers"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ContainerToComposeProject convert container config to compose project
|
||||||
|
func ContainerToComposeProject(r containers.ContainerConfig, containerID string) (types.Project, error) {
|
||||||
|
var ports []types.ServicePortConfig
|
||||||
|
for _, p := range r.Ports {
|
||||||
|
ports = append(ports, types.ServicePortConfig{
|
||||||
|
Target: p.ContainerPort,
|
||||||
|
Published: p.HostPort,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
projectVolumes, serviceConfigVolumes, err := GetRunVolumes(r.Volumes)
|
||||||
|
if err != nil {
|
||||||
|
return types.Project{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
project := types.Project{
|
||||||
|
Name: r.ID,
|
||||||
|
Services: []types.ServiceConfig{
|
||||||
|
{
|
||||||
|
Name: containerID,
|
||||||
|
Image: r.Image,
|
||||||
|
Ports: ports,
|
||||||
|
Labels: r.Labels,
|
||||||
|
Volumes: serviceConfigVolumes,
|
||||||
|
Environment: toComposeEnvs(r.Environment),
|
||||||
|
Deploy: &types.DeployConfig{
|
||||||
|
Resources: types.Resources{
|
||||||
|
Limits: &types.Resource{
|
||||||
|
NanoCPUs: fmt.Sprintf("%f", r.CPULimit),
|
||||||
|
MemoryBytes: types.UnitBytes(r.MemLimit.Value()),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Volumes: projectVolumes,
|
||||||
|
}
|
||||||
|
return project, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func toComposeEnvs(opts []string) types.MappingWithEquals {
|
||||||
|
result := map[string]*string{}
|
||||||
|
for _, env := range opts {
|
||||||
|
tokens := strings.Split(env, "=")
|
||||||
|
if len(tokens) > 1 {
|
||||||
|
result[tokens[0]] = &tokens[1]
|
||||||
|
} else {
|
||||||
|
result[env] = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
54
azure/convert/container_test.go
Normal file
54
azure/convert/container_test.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 Docker, Inc.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package convert
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/Azure/go-autorest/autorest/to"
|
||||||
|
"github.com/compose-spec/compose-go/types"
|
||||||
|
|
||||||
|
"github.com/docker/api/containers"
|
||||||
|
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ContainerConvertTestSuite struct {
|
||||||
|
suite.Suite
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *ContainerConvertTestSuite) TestConvertContainerEnvironment() {
|
||||||
|
container := containers.ContainerConfig{
|
||||||
|
ID: "container1",
|
||||||
|
Environment: []string{"key1=value1", "key2", "key3=value3"},
|
||||||
|
}
|
||||||
|
project, err := ContainerToComposeProject(container, "ID")
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
service1 := project.Services[0]
|
||||||
|
Expect(service1.Name).To(Equal("ID"))
|
||||||
|
Expect(service1.Environment).To(Equal(types.MappingWithEquals{
|
||||||
|
"key1": to.StringPtr("value1"),
|
||||||
|
"key2": nil,
|
||||||
|
"key3": to.StringPtr("value3"),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestContainerConvertTestSuite(t *testing.T) {
|
||||||
|
RegisterTestingT(t)
|
||||||
|
suite.Run(t, new(ContainerConvertTestSuite))
|
||||||
|
}
|
@ -22,6 +22,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math"
|
"math"
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -280,7 +281,8 @@ func (s serviceConfigAciHelper) getAciContainer(volumesCache map[string]bool) (c
|
|||||||
return containerinstance.Container{
|
return containerinstance.Container{
|
||||||
Name: to.StringPtr(s.Name),
|
Name: to.StringPtr(s.Name),
|
||||||
ContainerProperties: &containerinstance.ContainerProperties{
|
ContainerProperties: &containerinstance.ContainerProperties{
|
||||||
Image: to.StringPtr(s.Image),
|
Image: to.StringPtr(s.Image),
|
||||||
|
EnvironmentVariables: getEnvVariables(s.Environment),
|
||||||
Resources: &containerinstance.ResourceRequirements{
|
Resources: &containerinstance.ResourceRequirements{
|
||||||
Limits: &containerinstance.ResourceLimits{
|
Limits: &containerinstance.ResourceLimits{
|
||||||
MemoryInGB: to.Float64Ptr(memLimit),
|
MemoryInGB: to.Float64Ptr(memLimit),
|
||||||
@ -294,7 +296,23 @@ func (s serviceConfigAciHelper) getAciContainer(volumesCache map[string]bool) (c
|
|||||||
VolumeMounts: volumes,
|
VolumeMounts: volumes,
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getEnvVariables(composeEnv types.MappingWithEquals) *[]containerinstance.EnvironmentVariable {
|
||||||
|
result := []containerinstance.EnvironmentVariable{}
|
||||||
|
for key, value := range composeEnv {
|
||||||
|
var strValue string
|
||||||
|
if value == nil {
|
||||||
|
strValue = os.Getenv(key)
|
||||||
|
} else {
|
||||||
|
strValue = *value
|
||||||
|
}
|
||||||
|
result = append(result, containerinstance.EnvironmentVariable{
|
||||||
|
Name: to.StringPtr(key),
|
||||||
|
Value: to.StringPtr(strValue),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return &result
|
||||||
}
|
}
|
||||||
|
|
||||||
func bytesToGb(b types.UnitBytes) float64 {
|
func bytesToGb(b types.UnitBytes) float64 {
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package convert
|
package convert
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/Azure/azure-sdk-for-go/profiles/latest/containerinstance/mgmt/containerinstance"
|
"github.com/Azure/azure-sdk-for-go/profiles/latest/containerinstance/mgmt/containerinstance"
|
||||||
@ -260,6 +261,32 @@ func (suite *ConvertTestSuite) TestComposeContainerGroupToContainerResourceLimit
|
|||||||
Expect(*limits.MemoryInGB).To(Equal(float64(1)))
|
Expect(*limits.MemoryInGB).To(Equal(float64(1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *ConvertTestSuite) TestComposeContainerGroupToContainerenvVar() {
|
||||||
|
err := os.Setenv("key2", "value2")
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
project := types.Project{
|
||||||
|
Services: []types.ServiceConfig{
|
||||||
|
{
|
||||||
|
Name: "service1",
|
||||||
|
Image: "image1",
|
||||||
|
Environment: types.MappingWithEquals{
|
||||||
|
"key1": to.StringPtr("value1"),
|
||||||
|
"key2": nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
group, err := ToContainerGroup(suite.ctx, project)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
container1 := (*group.Containers)[0]
|
||||||
|
envVars := *container1.EnvironmentVariables
|
||||||
|
Expect(len(envVars)).To(Equal(2))
|
||||||
|
Expect(envVars).To(ContainElement(containerinstance.EnvironmentVariable{Name: to.StringPtr("key1"), Value: to.StringPtr("value1")}))
|
||||||
|
Expect(envVars).To(ContainElement(containerinstance.EnvironmentVariable{Name: to.StringPtr("key2"), Value: to.StringPtr("value2")}))
|
||||||
|
}
|
||||||
|
|
||||||
func TestConvertTestSuite(t *testing.T) {
|
func TestConvertTestSuite(t *testing.T) {
|
||||||
RegisterTestingT(t)
|
RegisterTestingT(t)
|
||||||
suite.Run(t, new(ConvertTestSuite))
|
suite.Run(t, new(ConvertTestSuite))
|
||||||
|
@ -51,6 +51,7 @@ func Command() *cobra.Command {
|
|||||||
cmd.Flags().BoolVarP(&opts.Detach, "detach", "d", false, "Run container in background and print container ID")
|
cmd.Flags().BoolVarP(&opts.Detach, "detach", "d", false, "Run container in background and print container ID")
|
||||||
cmd.Flags().Float64Var(&opts.Cpus, "cpus", 1., "Number of CPUs")
|
cmd.Flags().Float64Var(&opts.Cpus, "cpus", 1., "Number of CPUs")
|
||||||
cmd.Flags().VarP(&opts.Memory, "memory", "m", "Memory limit")
|
cmd.Flags().VarP(&opts.Memory, "memory", "m", "Memory limit")
|
||||||
|
cmd.Flags().StringArrayVarP(&opts.Environment, "env", "e", []string{}, "Set environment variables")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
1
cli/cmd/run/testdata/run-help.golden
vendored
1
cli/cmd/run/testdata/run-help.golden
vendored
@ -6,6 +6,7 @@ Usage:
|
|||||||
Flags:
|
Flags:
|
||||||
--cpus float Number of CPUs (default 1)
|
--cpus float Number of CPUs (default 1)
|
||||||
-d, --detach Run container in background and print container ID
|
-d, --detach Run container in background and print container ID
|
||||||
|
-e, --env stringArray Set environment variables
|
||||||
-l, --label stringArray Set meta data on a container
|
-l, --label stringArray Set meta data on a container
|
||||||
-m, --memory bytes Memory limit
|
-m, --memory bytes Memory limit
|
||||||
--name string Assign a name to the container
|
--name string Assign a name to the container
|
||||||
|
@ -30,13 +30,14 @@ import (
|
|||||||
|
|
||||||
// Opts contain run command options
|
// Opts contain run command options
|
||||||
type Opts struct {
|
type Opts struct {
|
||||||
Name string
|
Name string
|
||||||
Publish []string
|
Publish []string
|
||||||
Labels []string
|
Labels []string
|
||||||
Volumes []string
|
Volumes []string
|
||||||
Cpus float64
|
Cpus float64
|
||||||
Memory formatter.MemBytes
|
Memory formatter.MemBytes
|
||||||
Detach bool
|
Detach bool
|
||||||
|
Environment []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToContainerConfig convert run options to a container configuration
|
// ToContainerConfig convert run options to a container configuration
|
||||||
@ -56,13 +57,14 @@ func (r *Opts) ToContainerConfig(image string) (containers.ContainerConfig, erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
return containers.ContainerConfig{
|
return containers.ContainerConfig{
|
||||||
ID: r.Name,
|
ID: r.Name,
|
||||||
Image: image,
|
Image: image,
|
||||||
Ports: publish,
|
Ports: publish,
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
Volumes: r.Volumes,
|
Volumes: r.Volumes,
|
||||||
MemLimit: r.Memory,
|
MemLimit: r.Memory,
|
||||||
CPULimit: r.Cpus,
|
CPULimit: r.Cpus,
|
||||||
|
Environment: r.Environment,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +68,8 @@ type ContainerConfig struct {
|
|||||||
MemLimit formatter.MemBytes
|
MemLimit formatter.MemBytes
|
||||||
// CPUlimit
|
// CPUlimit
|
||||||
CPULimit float64
|
CPULimit float64
|
||||||
|
// Environment variables
|
||||||
|
Environment []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogsRequest contains configuration about a log request
|
// LogsRequest contains configuration about a log request
|
||||||
|
@ -302,6 +302,28 @@ func (s *E2eACISuite) TestACIBackend() {
|
|||||||
s.NewDockerCommand("compose", "down", "--project-name", composeProjectName).ExecOrDie()
|
s.NewDockerCommand("compose", "down", "--project-name", composeProjectName).ExecOrDie()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
s.T().Run("runs mysql with env variables", func(t *testing.T) {
|
||||||
|
err := os.Setenv("MYSQL_USER", "user1")
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
s.NewDockerCommand("run", "-d", "mysql:5.7", "-e", "MYSQL_ROOT_PASSWORD=rootpwd", "-e", "MYSQL_DATABASE=mytestdb", "-e", "MYSQL_USER", "-e", "MYSQL_PASSWORD=userpwd").ExecOrDie()
|
||||||
|
|
||||||
|
output := s.NewDockerCommand("ps").ExecOrDie()
|
||||||
|
lines := Lines(output)
|
||||||
|
Expect(len(lines)).To(Equal(2))
|
||||||
|
|
||||||
|
containerFields := Columns(lines[1])
|
||||||
|
containerID := containerFields[0]
|
||||||
|
Expect(containerFields[1]).To(Equal("mysql:5.7"))
|
||||||
|
Expect(containerFields[2]).To(Equal("Running"))
|
||||||
|
|
||||||
|
errs := make(chan error)
|
||||||
|
err = WaitFor(time.Second, 100*time.Second, errs, func() bool {
|
||||||
|
output = s.NewDockerCommand("logs", containerID).ExecOrDie()
|
||||||
|
return strings.Contains(output, "Giving user user1 access to schema mytestdb")
|
||||||
|
})
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
})
|
||||||
|
|
||||||
s.T().Run("switches back to default context", func(t *testing.T) {
|
s.T().Run("switches back to default context", func(t *testing.T) {
|
||||||
output := s.NewCommand("docker", "context", "use", "default").ExecOrDie()
|
output := s.NewCommand("docker", "context", "use", "default").ExecOrDie()
|
||||||
Expect(output).To(ContainSubstring("default"))
|
Expect(output).To(ContainSubstring("default"))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user