зеркало из https://github.com/docker/compose-cli.git
Коммит
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))
|
||||
}
|
||||
|
||||
var ports []types.ServicePortConfig
|
||||
for _, p := range r.Ports {
|
||||
ports = append(ports, types.ServicePortConfig{
|
||||
Target: p.ContainerPort,
|
||||
Published: p.HostPort,
|
||||
})
|
||||
}
|
||||
|
||||
projectVolumes, serviceConfigVolumes, err := convert.GetRunVolumes(r.Volumes)
|
||||
project, err := convert.ContainerToComposeProject(r, singleContainerName)
|
||||
if err != nil {
|
||||
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)
|
||||
groupDefinition, err := convert.ToContainerGroup(cs.ctx, project)
|
||||
if err != nil {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -281,6 +282,7 @@ func (s serviceConfigAciHelper) getAciContainer(volumesCache map[string]bool) (c
|
|||
Name: to.StringPtr(s.Name),
|
||||
ContainerProperties: &containerinstance.ContainerProperties{
|
||||
Image: to.StringPtr(s.Image),
|
||||
EnvironmentVariables: getEnvVariables(s.Environment),
|
||||
Resources: &containerinstance.ResourceRequirements{
|
||||
Limits: &containerinstance.ResourceLimits{
|
||||
MemoryInGB: to.Float64Ptr(memLimit),
|
||||
|
@ -294,7 +296,23 @@ func (s serviceConfigAciHelper) getAciContainer(volumesCache map[string]bool) (c
|
|||
VolumeMounts: volumes,
|
||||
},
|
||||
}, 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 {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package convert
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"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)))
|
||||
}
|
||||
|
||||
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) {
|
||||
RegisterTestingT(t)
|
||||
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().Float64Var(&opts.Cpus, "cpus", 1., "Number of CPUs")
|
||||
cmd.Flags().VarP(&opts.Memory, "memory", "m", "Memory limit")
|
||||
cmd.Flags().StringArrayVarP(&opts.Environment, "env", "e", []string{}, "Set environment variables")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ Usage:
|
|||
Flags:
|
||||
--cpus float Number of CPUs (default 1)
|
||||
-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
|
||||
-m, --memory bytes Memory limit
|
||||
--name string Assign a name to the container
|
||||
|
|
|
@ -37,6 +37,7 @@ type Opts struct {
|
|||
Cpus float64
|
||||
Memory formatter.MemBytes
|
||||
Detach bool
|
||||
Environment []string
|
||||
}
|
||||
|
||||
// ToContainerConfig convert run options to a container configuration
|
||||
|
@ -63,6 +64,7 @@ func (r *Opts) ToContainerConfig(image string) (containers.ContainerConfig, erro
|
|||
Volumes: r.Volumes,
|
||||
MemLimit: r.Memory,
|
||||
CPULimit: r.Cpus,
|
||||
Environment: r.Environment,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,8 @@ type ContainerConfig struct {
|
|||
MemLimit formatter.MemBytes
|
||||
// CPUlimit
|
||||
CPULimit float64
|
||||
// Environment variables
|
||||
Environment []string
|
||||
}
|
||||
|
||||
// LogsRequest contains configuration about a log request
|
||||
|
|
|
@ -302,6 +302,28 @@ func (s *E2eACISuite) TestACIBackend() {
|
|||
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) {
|
||||
output := s.NewCommand("docker", "context", "use", "default").ExecOrDie()
|
||||
Expect(output).To(ContainSubstring("default"))
|
||||
|
|
Загрузка…
Ссылка в новой задаче