Skip to content

Commit

Permalink
fix: don't use runtime-specs Mount struct in machine config
Browse files Browse the repository at this point in the history
First of all, it breaks our backwards compatibility promises and breaks
documentation generation. Upstream `specs.Mount` might change at any
time.

The issue was that containerd 1.7.x brings in new `specs.Mount` which
contains extra fields which don't have `omitempty` for YAML, so
machinery always generates them which confuses old Talos versions.

Use a copy of the upstream struct with proper YAML tags, and also
provide a special trick to make sure if the upstream struct changes, we
have a chance to update our copy of the struct.

Also this fixes docs and JSON schema.

Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
  • Loading branch information
smira committed Oct 11, 2023
1 parent d1b2792 commit 7bb205e
Show file tree
Hide file tree
Showing 9 changed files with 412 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,9 @@ func (suite *KubeletConfigSuite) TestReconcile() {
},
KubeletExtraMounts: []v1alpha1.ExtraMount{
{
Mount: specs.Mount{
Destination: "/tmp",
Source: "/var",
Type: "tmpfs",
},
Destination: "/tmp",
Source: "/var",
Type: "tmpfs",
},
},
KubeletExtraConfig: v1alpha1.Unstructured{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1353,7 +1353,59 @@
"type": "object"
},
"ExtraMount": {
"properties": {},
"properties": {
"destination": {
"type": "string",
"title": "destination",
"description": "Destination is the absolute path where the mount will be placed in the container.\n",
"markdownDescription": "Destination is the absolute path where the mount will be placed in the container.",
"x-intellij-html-description": "\u003cp\u003eDestination is the absolute path where the mount will be placed in the container.\u003c/p\u003e\n"
},
"type": {
"type": "string",
"title": "type",
"description": "Type specifies the mount kind.\n",
"markdownDescription": "Type specifies the mount kind.",
"x-intellij-html-description": "\u003cp\u003eType specifies the mount kind.\u003c/p\u003e\n"
},
"source": {
"type": "string",
"title": "source",
"description": "Source specifies the source path of the mount.\n",
"markdownDescription": "Source specifies the source path of the mount.",
"x-intellij-html-description": "\u003cp\u003eSource specifies the source path of the mount.\u003c/p\u003e\n"
},
"options": {
"items": {
"type": "string"
},
"type": "array",
"title": "options",
"description": "Options are fstab style mount options.\n",
"markdownDescription": "Options are fstab style mount options.",
"x-intellij-html-description": "\u003cp\u003eOptions are fstab style mount options.\u003c/p\u003e\n"
},
"uidMappings": {
"items": {
"$ref": "#/$defs/LinuxIDMapping"
},
"type": "array",
"title": "uidMappings",
"description": "UID/GID mappings used for changing file owners w/o calling chown, fs should support it.\n\nEvery mount point could have its own mapping.\n",
"markdownDescription": "UID/GID mappings used for changing file owners w/o calling chown, fs should support it.\n\nEvery mount point could have its own mapping.",
"x-intellij-html-description": "\u003cp\u003eUID/GID mappings used for changing file owners w/o calling chown, fs should support it.\u003c/p\u003e\n\n\u003cp\u003eEvery mount point could have its own mapping.\u003c/p\u003e\n"
},
"gidMappings": {
"items": {
"$ref": "#/$defs/LinuxIDMapping"
},
"type": "array",
"title": "gidMappings",
"description": "UID/GID mappings used for changing file owners w/o calling chown, fs should support it.\n\nEvery mount point could have its own mapping.\n",
"markdownDescription": "UID/GID mappings used for changing file owners w/o calling chown, fs should support it.\n\nEvery mount point could have its own mapping.",
"x-intellij-html-description": "\u003cp\u003eUID/GID mappings used for changing file owners w/o calling chown, fs should support it.\u003c/p\u003e\n\n\u003cp\u003eEvery mount point could have its own mapping.\u003c/p\u003e\n"
}
},
"additionalProperties": false,
"type": "object"
},
Expand Down Expand Up @@ -1771,6 +1823,33 @@
"additionalProperties": false,
"type": "object"
},
"LinuxIDMapping": {
"properties": {
"containerID": {
"type": "integer",
"title": "containerID",
"description": "ContainerID is the starting UID/GID in the container.\n",
"markdownDescription": "ContainerID is the starting UID/GID in the container.",
"x-intellij-html-description": "\u003cp\u003eContainerID is the starting UID/GID in the container.\u003c/p\u003e\n"
},
"hostID": {
"type": "integer",
"title": "hostID",
"description": "HostID is the starting UID/GID on the host to be mapped to ‘ContainerID’.\n",
"markdownDescription": "HostID is the starting UID/GID on the host to be mapped to 'ContainerID'.",
"x-intellij-html-description": "\u003cp\u003eHostID is the starting UID/GID on the host to be mapped to \u0026lsquo;ContainerID\u0026rsquo;.\u003c/p\u003e\n"
},
"size": {
"type": "integer",
"title": "size",
"description": "Size is the number of IDs to be mapped.\n",
"markdownDescription": "Size is the number of IDs to be mapped.",
"x-intellij-html-description": "\u003cp\u003eSize is the number of IDs to be mapped.\u003c/p\u003e\n"
}
},
"additionalProperties": false,
"type": "object"
},
"LoggingConfig": {
"properties": {
"destinations": {
Expand Down
17 changes: 7 additions & 10 deletions pkg/machinery/config/types/v1alpha1/v1alpha1_examples.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"strings"
"time"

specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/siderolabs/crypto/x509"
"github.com/siderolabs/go-pointer"
"gopkg.in/yaml.v3"
Expand Down Expand Up @@ -475,15 +474,13 @@ func clusterEndpointExample2() *Endpoint {
func kubeletExtraMountsExample() []ExtraMount {
return []ExtraMount{
{
specs.Mount{
Source: "/var/lib/example",
Destination: "/var/lib/example",
Type: "bind",
Options: []string{
"bind",
"rshared",
"rw",
},
Source: "/var/lib/example",
Destination: "/var/lib/example",
Type: "bind",
Options: []string{
"bind",
"rshared",
"rw",
},
},
}
Expand Down
28 changes: 27 additions & 1 deletion pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,33 @@ func (k *KubeletConfig) ExtraArgs() map[string]string {

// ExtraMounts implements the config.Provider interface.
func (k *KubeletConfig) ExtraMounts() []specs.Mount {
return xslices.Map(k.KubeletExtraMounts, func(m ExtraMount) specs.Mount { return m.Mount })
// use the intermediate type which is assignable to specs.Mount so that
// we can be sure that `specs.Mount` and `Mount` have exactly same fields.
//
// as in Go []T1 is not assignable to []T2, even if T1 and T2 are assignable, we cannot
// use direct conversion of Mount and specs.Mount
type mountConverter struct {
Destination string
Type string
Source string
Options []string
UIDMappings []specs.LinuxIDMapping
GIDMappings []specs.LinuxIDMapping
}

return xslices.Map(k.KubeletExtraMounts,
func(m ExtraMount) specs.Mount {
return specs.Mount(func() mountConverter {
return mountConverter{
Destination: m.Destination,
Type: m.Type,
Source: m.Source,
Options: m.Options,
UIDMappings: xslices.Map(m.UIDMappings, func(m LinuxIDMapping) specs.LinuxIDMapping { return specs.LinuxIDMapping(m) }),
GIDMappings: xslices.Map(m.GIDMappings, func(m LinuxIDMapping) specs.LinuxIDMapping { return specs.LinuxIDMapping(m) }),
}
}())
})
}

// ExtraConfig implements the config.Provider interface.
Expand Down
53 changes: 35 additions & 18 deletions pkg/machinery/config/types/v1alpha1/v1alpha1_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
"time"

"github.com/dustin/go-humanize"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/siderolabs/crypto/x509"
"github.com/siderolabs/go-blockdevice/blockdevice/util/disk"
"gopkg.in/yaml.v3"
Expand Down Expand Up @@ -492,26 +491,44 @@ type ClusterConfig struct {
AllowSchedulingOnControlPlanes *bool `yaml:"allowSchedulingOnControlPlanes,omitempty"`
}

// ExtraMount wraps OCI Mount specification.
type ExtraMount struct {
specs.Mount `yaml:",inline"`
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExtraMount) DeepCopyInto(out *ExtraMount) {
*out = *in
// LinuxIDMapping represents the Linux ID mapping.
type LinuxIDMapping struct {
// description: |
// ContainerID is the starting UID/GID in the container.
ContainerID uint32 `yaml:"containerID"`
// description: |
// HostID is the starting UID/GID on the host to be mapped to 'ContainerID'.
HostID uint32 `yaml:"hostID"`
// description: |
// Size is the number of IDs to be mapped.
Size uint32 `yaml:"size"`
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtraMount.
func (in *ExtraMount) DeepCopy() *ExtraMount {
if in == nil {
return nil
}

out := new(ExtraMount)
in.DeepCopyInto(out)
// ExtraMount wraps OCI Mount specification.
type ExtraMount struct {
// description: |
// Destination is the absolute path where the mount will be placed in the container.
Destination string `yaml:"destination"`
// description: |
// Type specifies the mount kind.
Type string `yaml:"type,omitempty"`
// description: |
// Source specifies the source path of the mount.
Source string `yaml:"source,omitempty"`
// description: |
// Options are fstab style mount options.
Options []string `yaml:"options,omitempty"`

return out
// description: |
// UID/GID mappings used for changing file owners w/o calling chown, fs should support it.
//
// Every mount point could have its own mapping.
UIDMappings []LinuxIDMapping `yaml:"uidMappings,omitempty"`
// description: |
// UID/GID mappings used for changing file owners w/o calling chown, fs should support it.
//
// Every mount point could have its own mapping.
GIDMappings []LinuxIDMapping `yaml:"gidMappings,omitempty"`
}

// MachineControlPlaneConfig machine specific configuration options.
Expand Down
89 changes: 88 additions & 1 deletion pkg/machinery/config/types/v1alpha1/v1alpha1_types_doc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 7bb205e

Please sign in to comment.