mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-19 09:16:29 +00:00
Merge pull request #3511 from deitch/append-binds
support merge yaml flags
This commit is contained in:
commit
9d5a22d44a
@ -144,7 +144,9 @@ options. Default values may be specified using the `org.mobyproject.config` imag
|
|||||||
For more details see the [OCI specification](https://github.com/opencontainers/runtime-spec/blob/master/spec.md).
|
For more details see the [OCI specification](https://github.com/opencontainers/runtime-spec/blob/master/spec.md).
|
||||||
|
|
||||||
If the `org.mobylinux.config` label is set in the image, that specifies default values for these fields if they
|
If the `org.mobylinux.config` label is set in the image, that specifies default values for these fields if they
|
||||||
are not set in the yaml file. You can override the label by setting the value, or setting it to be empty to remove
|
are not set in the yaml file. While most fields are _replaced_ if they are specified in the yaml file,
|
||||||
|
some support _add_ via the format `<field>.add`; see below.
|
||||||
|
You can override the label entirely by setting the value, or setting it to be empty to remove
|
||||||
the specification for that value in the label.
|
the specification for that value in the label.
|
||||||
|
|
||||||
If you need an OCI option that is not specified here please open an issue or pull request as the list is not yet
|
If you need an OCI option that is not specified here please open an issue or pull request as the list is not yet
|
||||||
@ -159,6 +161,7 @@ bind mounted into a container.
|
|||||||
extracted from this so they need not be filled in.
|
extracted from this so they need not be filled in.
|
||||||
- `capabilities` the Linux capabilities required, for example `CAP_SYS_ADMIN`. If there is a single
|
- `capabilities` the Linux capabilities required, for example `CAP_SYS_ADMIN`. If there is a single
|
||||||
capability `all` then all capabilities are added.
|
capability `all` then all capabilities are added.
|
||||||
|
- `capabilities.add` the Linux capabilities required, but these are added to the defaults, rather than overriding them.
|
||||||
- `ambient` the Linux ambient capabilities (capabilities passed to non root users) that are required.
|
- `ambient` the Linux ambient capabilities (capabilities passed to non root users) that are required.
|
||||||
- `mounts` is the full form for specifying a mount, which requires `type`, `source`, `destination`
|
- `mounts` is the full form for specifying a mount, which requires `type`, `source`, `destination`
|
||||||
and a list of `options`. If any fields are omitted, sensible defaults are used if possible, for example
|
and a list of `options`. If any fields are omitted, sensible defaults are used if possible, for example
|
||||||
@ -166,6 +169,7 @@ bind mounted into a container.
|
|||||||
can be replaced by specifying a mount with new options here at the same mount point.
|
can be replaced by specifying a mount with new options here at the same mount point.
|
||||||
- `binds` is a simpler interface to specify bind mounts, accepting a string like `/src:/dest:opt1,opt2`
|
- `binds` is a simpler interface to specify bind mounts, accepting a string like `/src:/dest:opt1,opt2`
|
||||||
similar to the `-v` option for bind mounts in Docker.
|
similar to the `-v` option for bind mounts in Docker.
|
||||||
|
- `binds.add` is a simpler interface to specify bind mounts, but these are added to the defaults, rather than overriding them.
|
||||||
- `tmpfs` is a simpler interface to mount a `tmpfs`, like `--tmpfs` in Docker, taking `/dest:opt1,opt2`.
|
- `tmpfs` is a simpler interface to mount a `tmpfs`, like `--tmpfs` in Docker, taking `/dest:opt1,opt2`.
|
||||||
- `command` will override the command and entrypoint in the image with a new list of commands.
|
- `command` will override the command and entrypoint in the image with a new list of commands.
|
||||||
- `env` will override the environment in the image with a new environment list. Specify variables as `VAR=value`.
|
- `env` will override the environment in the image with a new environment list. Specify variables as `VAR=value`.
|
||||||
|
29
examples/addbinds.yml
Normal file
29
examples/addbinds.yml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
kernel:
|
||||||
|
image: linuxkit/kernel:5.4.30
|
||||||
|
cmdline: "console=tty0 console=ttyS0 console=ttyAMA0 console=ttysclp0"
|
||||||
|
init:
|
||||||
|
- linuxkit/init:7195dc244cd92af01fd0895fd204249a6114c5e2
|
||||||
|
- linuxkit/runc:f79954950022fea76b8b6f10de58cb48e4fb3878
|
||||||
|
- linuxkit/containerd:8ee7a0d636fff9df7e13076f5492d06274e5f644
|
||||||
|
- linuxkit/ca-certificates:abfc6701b9ca17e34ac9439ce5946a247e720ff5
|
||||||
|
onboot:
|
||||||
|
- name: sysctl
|
||||||
|
image: linuxkit/sysctl:541f60fe3676611328e89e8bac251fc636b1a6aa
|
||||||
|
- name: dhcpcd
|
||||||
|
image: linuxkit/dhcpcd:2f8a9b670aa6e96a09db56ec45c9f07ef2a811ee
|
||||||
|
command: ["/sbin/dhcpcd", "--nobackground", "-f", "/dhcpcd.conf", "-1"]
|
||||||
|
services:
|
||||||
|
- name: getty
|
||||||
|
image: linuxkit/getty:48f66df198981e692084bf70ab72b9fe2be0f880
|
||||||
|
binds.add:
|
||||||
|
# this will keep all of the existing ones as well
|
||||||
|
- /var/tmp:/var/tmp
|
||||||
|
- name: rngd
|
||||||
|
image: linuxkit/rngd:7fab61cca793113280397dcee8159f35dc37adcb
|
||||||
|
files:
|
||||||
|
- path: etc/getty.shadow
|
||||||
|
# sample sets password for root to "abcdefgh" (without quotes)
|
||||||
|
contents: 'root:$6$6tPd2uhHrecCEKug$8mKfcgfwguP7f.BLdZsT1Wz7WIIJOBY1oUFHzIv9/O71M2J0EPdtFqFGTxB1UK5ejqQxRFQ.ZSG9YXR0SNsc11:17322:0:::::'
|
||||||
|
trust:
|
||||||
|
org:
|
||||||
|
- linuxkit
|
@ -71,9 +71,11 @@ type Image struct {
|
|||||||
// Everything except Runtime and ref is used to build the OCI spec
|
// Everything except Runtime and ref is used to build the OCI spec
|
||||||
type ImageConfig struct {
|
type ImageConfig struct {
|
||||||
Capabilities *[]string `yaml:"capabilities,omitempty" json:"capabilities,omitempty"`
|
Capabilities *[]string `yaml:"capabilities,omitempty" json:"capabilities,omitempty"`
|
||||||
|
CapabilitiesAdd *[]string `yaml:"capabilities.add,omitempty" json:"capabilities.add,omitempty"`
|
||||||
Ambient *[]string `yaml:"ambient,omitempty" json:"ambient,omitempty"`
|
Ambient *[]string `yaml:"ambient,omitempty" json:"ambient,omitempty"`
|
||||||
Mounts *[]specs.Mount `yaml:"mounts,omitempty" json:"mounts,omitempty"`
|
Mounts *[]specs.Mount `yaml:"mounts,omitempty" json:"mounts,omitempty"`
|
||||||
Binds *[]string `yaml:"binds,omitempty" json:"binds,omitempty"`
|
Binds *[]string `yaml:"binds,omitempty" json:"binds,omitempty"`
|
||||||
|
BindsAdd *[]string `yaml:"binds.add,omitempty" json:"binds.add,omitempty"`
|
||||||
Tmpfs *[]string `yaml:"tmpfs,omitempty" json:"tmpfs,omitempty"`
|
Tmpfs *[]string `yaml:"tmpfs,omitempty" json:"tmpfs,omitempty"`
|
||||||
Command *[]string `yaml:"command,omitempty" json:"command,omitempty"`
|
Command *[]string `yaml:"command,omitempty" json:"command,omitempty"`
|
||||||
Env *[]string `yaml:"env,omitempty" json:"env,omitempty"`
|
Env *[]string `yaml:"env,omitempty" json:"env,omitempty"`
|
||||||
@ -505,6 +507,34 @@ func assignStrings3(v1 []string, v2, v3 *[]string) []string {
|
|||||||
return v1
|
return v1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mergeStrings does ordered unique merge between JSON string array pointers
|
||||||
|
func mergeStrings(v1, v2 *[]string) *[]string {
|
||||||
|
switch {
|
||||||
|
case v2 == nil && v1 == nil:
|
||||||
|
return &[]string{}
|
||||||
|
case v2 == nil:
|
||||||
|
return v1
|
||||||
|
case v1 == nil:
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
// merge the two uniquely
|
||||||
|
ret := []string{}
|
||||||
|
m := make(map[string]bool)
|
||||||
|
for _, s := range *v1 {
|
||||||
|
if m[s] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ret = append(ret, s)
|
||||||
|
}
|
||||||
|
for _, s := range *v2 {
|
||||||
|
if m[s] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ret = append(ret, s)
|
||||||
|
}
|
||||||
|
return &ret
|
||||||
|
}
|
||||||
|
|
||||||
// assignMaps does ordered overrides from JSON string map pointers
|
// assignMaps does ordered overrides from JSON string map pointers
|
||||||
func assignMaps(v1, v2 *map[string]string) map[string]string {
|
func assignMaps(v1, v2 *map[string]string) map[string]string {
|
||||||
if v2 != nil {
|
if v2 != nil {
|
||||||
@ -770,7 +800,7 @@ func ConfigInspectToOCI(yaml *Image, inspect types.ImageInspect, idMap map[strin
|
|||||||
}
|
}
|
||||||
mounts[dest] = specs.Mount{Destination: dest, Type: "tmpfs", Source: "tmpfs", Options: opts}
|
mounts[dest] = specs.Mount{Destination: dest, Type: "tmpfs", Source: "tmpfs", Options: opts}
|
||||||
}
|
}
|
||||||
for _, b := range assignStrings(label.Binds, yaml.Binds) {
|
for _, b := range assignStrings(mergeStrings(label.Binds, yaml.BindsAdd), yaml.Binds) {
|
||||||
parts := strings.Split(b, ":")
|
parts := strings.Split(b, ":")
|
||||||
if len(parts) < 2 {
|
if len(parts) < 2 {
|
||||||
return oci, runtime, fmt.Errorf("Cannot parse bind, missing ':': %s", b)
|
return oci, runtime, fmt.Errorf("Cannot parse bind, missing ':': %s", b)
|
||||||
@ -880,7 +910,7 @@ func ConfigInspectToOCI(yaml *Image, inspect types.ImageInspect, idMap map[strin
|
|||||||
capCheck[capability] = true
|
capCheck[capability] = true
|
||||||
}
|
}
|
||||||
boundingSet := map[string]bool{}
|
boundingSet := map[string]bool{}
|
||||||
caps := assignStrings(label.Capabilities, yaml.Capabilities)
|
caps := assignStrings(mergeStrings(label.Capabilities, yaml.CapabilitiesAdd), yaml.Capabilities)
|
||||||
if len(caps) == 1 {
|
if len(caps) == 1 {
|
||||||
switch cap := strings.ToLower(caps[0]); cap {
|
switch cap := strings.ToLower(caps[0]); cap {
|
||||||
case "none":
|
case "none":
|
||||||
|
@ -260,9 +260,11 @@ var schema = string(`
|
|||||||
"name": {"type": "string"},
|
"name": {"type": "string"},
|
||||||
"image": {"type": "string"},
|
"image": {"type": "string"},
|
||||||
"capabilities": { "$ref": "#/definitions/strings" },
|
"capabilities": { "$ref": "#/definitions/strings" },
|
||||||
|
"capabilities.add": { "$ref": "#/definitions/strings" },
|
||||||
"ambient": { "$ref": "#/definitions/strings" },
|
"ambient": { "$ref": "#/definitions/strings" },
|
||||||
"mounts": { "$ref": "#/definitions/mounts" },
|
"mounts": { "$ref": "#/definitions/mounts" },
|
||||||
"binds": { "$ref": "#/definitions/strings" },
|
"binds": { "$ref": "#/definitions/strings" },
|
||||||
|
"binds.add": { "$ref": "#/definitions/strings" },
|
||||||
"tmpfs": { "$ref": "#/definitions/strings" },
|
"tmpfs": { "$ref": "#/definitions/strings" },
|
||||||
"command": { "$ref": "#/definitions/strings" },
|
"command": { "$ref": "#/definitions/strings" },
|
||||||
"env": { "$ref": "#/definitions/strings" },
|
"env": { "$ref": "#/definitions/strings" },
|
||||||
|
15
test/cases/000_build/020_binds/check.sh
Executable file
15
test/cases/000_build/020_binds/check.sh
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -x
|
||||||
|
|
||||||
|
function failed {
|
||||||
|
printf "bindmerge test suite FAILED\n" >&1
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# the very fact that this is running means that the bind worked, so just need to check that the defaults also
|
||||||
|
# are there
|
||||||
|
|
||||||
|
[ -d /dev/mapper ] || failed
|
||||||
|
[ -d /hostroot ] || failed
|
||||||
|
printf "bindmerge test suite PASSED\n" >&1
|
27
test/cases/000_build/020_binds/test.sh
Executable file
27
test/cases/000_build/020_binds/test.sh
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# SUMMARY: Check that the userdata is found and read when on a cidata partition
|
||||||
|
# LABELS:
|
||||||
|
# REPEAT:
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
# Source libraries. Uncomment if needed/defined
|
||||||
|
#. "${RT_LIB}"
|
||||||
|
. "${RT_PROJECT_ROOT}/_lib/lib.sh"
|
||||||
|
|
||||||
|
NAME=bindtest
|
||||||
|
DISK=disk.img
|
||||||
|
|
||||||
|
clean_up() {
|
||||||
|
rm -rf ${NAME}-* ${DISK}
|
||||||
|
}
|
||||||
|
trap clean_up EXIT
|
||||||
|
|
||||||
|
# Test code goes here
|
||||||
|
|
||||||
|
linuxkit build -format kernel+initrd -name ${NAME} test.yml
|
||||||
|
RESULT="$(linuxkit run -disk file=${DISK},size=32M ${NAME})"
|
||||||
|
echo "${RESULT}"
|
||||||
|
echo "${RESULT}" | grep -q "suite PASSED"
|
||||||
|
|
||||||
|
exit 0
|
28
test/cases/000_build/020_binds/test.yml
Normal file
28
test/cases/000_build/020_binds/test.yml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
kernel:
|
||||||
|
image: linuxkit/kernel:5.4.30
|
||||||
|
cmdline: "console=ttyS0 console=ttyAMA0"
|
||||||
|
init:
|
||||||
|
- linuxkit/init:7195dc244cd92af01fd0895fd204249a6114c5e2
|
||||||
|
- linuxkit/runc:f79954950022fea76b8b6f10de58cb48e4fb3878
|
||||||
|
onboot:
|
||||||
|
- name: mount
|
||||||
|
image: linuxkit/mount:19fa297189166206ac97261679c3e31fb140d48f
|
||||||
|
binds.add:
|
||||||
|
- /check.sh:/check.sh
|
||||||
|
- /var/tmp:/var/tmp
|
||||||
|
# default binds from linuxkit/mount
|
||||||
|
# - /dev:/dev
|
||||||
|
# - /var:/var:rshared,rbind
|
||||||
|
# - /:/hostroot
|
||||||
|
command: ["sh", "-c", "/check.sh"]
|
||||||
|
- name: poweroff
|
||||||
|
image: linuxkit/poweroff:06dd4e46c62fbe79123a028835c921f80e4855d3
|
||||||
|
command: ["/bin/sh", "/poweroff.sh", "10"]
|
||||||
|
files:
|
||||||
|
- path: check.sh
|
||||||
|
source: ./check.sh
|
||||||
|
mode: "0700"
|
||||||
|
trust:
|
||||||
|
org:
|
||||||
|
- linuxkit
|
||||||
|
- library
|
Loading…
Reference in New Issue
Block a user