mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-26 19:13:34 +00:00
feat: add support for cap_add and cap_drop compose keys (#238)
This commit is contained in:
@@ -605,6 +605,8 @@ func (s *Server) CreateServiceContainer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
hostConfig := &container.HostConfig{
|
hostConfig := &container.HostConfig{
|
||||||
|
CapAdd: spec.Container.CapAdd,
|
||||||
|
CapDrop: spec.Container.CapDrop,
|
||||||
Binds: spec.Container.Volumes,
|
Binds: spec.Container.Volumes,
|
||||||
Init: spec.Container.Init,
|
Init: spec.Container.Init,
|
||||||
Mounts: mounts,
|
Mounts: mounts,
|
||||||
|
|||||||
@@ -225,6 +225,10 @@ func (s *ServiceSpec) Clone() ServiceSpec {
|
|||||||
// ContainerSpec defines the desired state of a container in a service.
|
// ContainerSpec defines the desired state of a container in a service.
|
||||||
// ATTENTION: after changing this struct, verify if deploy.EvalContainerSpecChange needs to be updated.
|
// ATTENTION: after changing this struct, verify if deploy.EvalContainerSpecChange needs to be updated.
|
||||||
type ContainerSpec struct {
|
type ContainerSpec struct {
|
||||||
|
// Specifies which additional capabilities should be added for the container.
|
||||||
|
CapAdd []string
|
||||||
|
// Specifies which capabilities should be dropped from the container.
|
||||||
|
CapDrop []string
|
||||||
// Command overrides the default CMD of the image to be executed when running a container.
|
// Command overrides the default CMD of the image to be executed when running a container.
|
||||||
Command []string
|
Command []string
|
||||||
// Entrypoint overrides the default ENTRYPOINT of the image.
|
// Entrypoint overrides the default ENTRYPOINT of the image.
|
||||||
@@ -343,6 +347,14 @@ func (s *ContainerSpec) Clone() ContainerSpec {
|
|||||||
spec.ConfigMounts[i] = cm.Clone()
|
spec.ConfigMounts[i] = cm.Clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if s.CapAdd != nil {
|
||||||
|
spec.CapAdd = make([]string, len(s.CapAdd))
|
||||||
|
copy(spec.CapAdd, s.CapAdd)
|
||||||
|
}
|
||||||
|
if s.CapDrop != nil {
|
||||||
|
spec.CapDrop = make([]string, len(s.CapDrop))
|
||||||
|
copy(spec.CapDrop, s.CapDrop)
|
||||||
|
}
|
||||||
|
|
||||||
return spec
|
return spec
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -209,6 +209,8 @@ func TestServiceSpec_Validate_CaddyAndPorts(t *testing.T) {
|
|||||||
func TestContainerSpec_Clone(t *testing.T) {
|
func TestContainerSpec_Clone(t *testing.T) {
|
||||||
mode := os.FileMode(0o644)
|
mode := os.FileMode(0o644)
|
||||||
original := ContainerSpec{
|
original := ContainerSpec{
|
||||||
|
CapAdd: []string{"NET_ADMIN"},
|
||||||
|
CapDrop: []string{"ALL"},
|
||||||
Command: []string{"sh", "-c", "echo hello"},
|
Command: []string{"sh", "-c", "echo hello"},
|
||||||
Entrypoint: []string{"/bin/bash"},
|
Entrypoint: []string{"/bin/bash"},
|
||||||
Env: EnvVars{
|
Env: EnvVars{
|
||||||
@@ -247,6 +249,8 @@ func TestContainerSpec_Clone(t *testing.T) {
|
|||||||
|
|
||||||
// Verify deep copy by modifying the original
|
// Verify deep copy by modifying the original
|
||||||
stringModified := "modified"
|
stringModified := "modified"
|
||||||
|
original.CapAdd[0] = stringModified
|
||||||
|
original.CapDrop[0] = stringModified
|
||||||
original.Command[0] = stringModified
|
original.Command[0] = stringModified
|
||||||
original.Entrypoint[0] = stringModified
|
original.Entrypoint[0] = stringModified
|
||||||
original.Env["FOO"] = stringModified
|
original.Env["FOO"] = stringModified
|
||||||
@@ -258,6 +262,8 @@ func TestContainerSpec_Clone(t *testing.T) {
|
|||||||
|
|
||||||
assert.False(t, original.Equals(cloned))
|
assert.False(t, original.Equals(cloned))
|
||||||
// Assert cloned values are unchanged
|
// Assert cloned values are unchanged
|
||||||
|
assert.Equal(t, "NET_ADMIN", cloned.CapAdd[0])
|
||||||
|
assert.Equal(t, "ALL", cloned.CapDrop[0])
|
||||||
assert.Equal(t, "sh", cloned.Command[0])
|
assert.Equal(t, "sh", cloned.Command[0])
|
||||||
assert.Equal(t, "/bin/bash", cloned.Entrypoint[0])
|
assert.Equal(t, "/bin/bash", cloned.Entrypoint[0])
|
||||||
assert.Equal(t, "bar", cloned.Env["FOO"])
|
assert.Equal(t, "bar", cloned.Env["FOO"])
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ func ServiceSpecFromCompose(project *types.Project, serviceName string) (api.Ser
|
|||||||
|
|
||||||
spec := api.ServiceSpec{
|
spec := api.ServiceSpec{
|
||||||
Container: api.ContainerSpec{
|
Container: api.ContainerSpec{
|
||||||
|
CapAdd: service.CapAdd,
|
||||||
|
CapDrop: service.CapDrop,
|
||||||
Command: service.Command,
|
Command: service.Command,
|
||||||
Entrypoint: service.Entrypoint,
|
Entrypoint: service.Entrypoint,
|
||||||
Env: env,
|
Env: env,
|
||||||
|
|||||||
@@ -100,6 +100,8 @@ func TestServiceSpecFromCompose(t *testing.T) {
|
|||||||
Name: "test",
|
Name: "test",
|
||||||
Mode: api.ServiceModeReplicated,
|
Mode: api.ServiceModeReplicated,
|
||||||
Container: api.ContainerSpec{
|
Container: api.ContainerSpec{
|
||||||
|
CapAdd: []string{"NET_ADMIN"},
|
||||||
|
CapDrop: []string{"ALL"},
|
||||||
Command: []string{"nginx", "updated", "command"},
|
Command: []string{"nginx", "updated", "command"},
|
||||||
Entrypoint: []string{"/updated-docker-entrypoint.sh"},
|
Entrypoint: []string{"/updated-docker-entrypoint.sh"},
|
||||||
Env: map[string]string{
|
Env: map[string]string{
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
services:
|
services:
|
||||||
test:
|
test:
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
cap_drop:
|
||||||
|
- ALL
|
||||||
command: ["nginx", "updated", "command"]
|
command: ["nginx", "updated", "command"]
|
||||||
cpus: 0.5
|
cpus: 0.5
|
||||||
entrypoint: ["/updated-docker-entrypoint.sh"]
|
entrypoint: ["/updated-docker-entrypoint.sh"]
|
||||||
|
|||||||
@@ -9,6 +9,44 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestEvalContainerSpecChange_ContainerCapAdd(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
currentSpec := api.ServiceSpec{
|
||||||
|
Container: api.ContainerSpec{
|
||||||
|
Image: "nginx:latest",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
newSpec := api.ServiceSpec{
|
||||||
|
Container: api.ContainerSpec{
|
||||||
|
Image: "nginx:latest",
|
||||||
|
CapAdd: []string{"NET_ADMIN"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, ContainerNeedsRecreate, EvalContainerSpecChange(currentSpec, newSpec))
|
||||||
|
assert.Equal(t, ContainerNeedsRecreate, EvalContainerSpecChange(newSpec, currentSpec))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvalContainerSpecChange_ContainerCapDrop(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
currentSpec := api.ServiceSpec{
|
||||||
|
Container: api.ContainerSpec{
|
||||||
|
Image: "nginx:latest",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
newSpec := api.ServiceSpec{
|
||||||
|
Container: api.ContainerSpec{
|
||||||
|
Image: "nginx:latest",
|
||||||
|
CapDrop: []string{"ALL"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, ContainerNeedsRecreate, EvalContainerSpecChange(currentSpec, newSpec))
|
||||||
|
assert.Equal(t, ContainerNeedsRecreate, EvalContainerSpecChange(newSpec, currentSpec))
|
||||||
|
}
|
||||||
|
|
||||||
func TestEvalContainerSpecChange_ContainerResources(t *testing.T) {
|
func TestEvalContainerSpecChange_ContainerResources(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ The following table shows the support status for main Compose features:
|
|||||||
|--------------------|--------------------|---------------------------------------------------------------------------------------|
|
|--------------------|--------------------|---------------------------------------------------------------------------------------|
|
||||||
| **Services** | | |
|
| **Services** | | |
|
||||||
| `build` | ⚠️ Limited | Build context and Dockerfile |
|
| `build` | ⚠️ Limited | Build context and Dockerfile |
|
||||||
|
| `cap_add` | ✅ Supported | Additional kernel capabilities |
|
||||||
|
| `cap_drop` | ✅ Supported | Which capabilities to drop |
|
||||||
| `command` | ✅ Supported | Override container command |
|
| `command` | ✅ Supported | Override container command |
|
||||||
| `configs` | ✅ Supported | File-based and inline configs |
|
| `configs` | ✅ Supported | File-based and inline configs |
|
||||||
| `cpus` | ✅ Supported | CPU limit |
|
| `cpus` | ✅ Supported | CPU limit |
|
||||||
|
|||||||
Reference in New Issue
Block a user