Skip to content

Commit

Permalink
feat: support setting hostname to the machine name
Browse files Browse the repository at this point in the history
Fixes #131

Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
  • Loading branch information
smira committed Feb 2, 2022
1 parent 36fb7cc commit c7a7265
Show file tree
Hide file tree
Showing 14 changed files with 246 additions and 29 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ Fields available in the `TalosConfigTemplate` (and `TalosConfig`) resources:
It is recommended to always set this field explicitly to avoid issues when CABPT is upgraded to the version which supports new Talos version.
- `configPatches` (optional): set of machine configuration patches to apply to the generated configuration.
- `data` (only for `generateType: none`): user-supplied machine configuration.
- `hostname` (optional): configure hostname in the generate machine configuration:
- `source` (`MachineName`): set the hostname in the generated machine configuration to the `Machine` name (not supported with `MachinePool` deployments)

### Generated Machine Configuration

Expand Down
16 changes: 16 additions & 0 deletions api/v1alpha3/talosconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,25 @@ type TalosConfigSpec struct {
GenerateType string `json:"generateType"` //none,init,controlplane,worker mutually exclusive w/ data
Data string `json:"data,omitempty"`
ConfigPatches []ConfigPatches `json:"configPatches,omitempty"`
// Set hostname in the machine configuration to some value.
Hostname HostnameSpec `json:"hostname,omitempty"`
// Important: Run "make" to regenerate code after modifying this file
}

// HostnameSource is the definition of hostname source.
type HostnameSource string

// HostnameSourceMachineName sets the hostname in the generated configuration to the machine name.
const HostnameSourceMachineName HostnameSource = "MachineName"

// HostnameSpec defines the hostname source.
type HostnameSpec struct {
// Source of the hostname.
//
// Allowed values: "MachineName" (use linked Machine's Name).
Source HostnameSource `json:"source,omitempty"`
}

// TalosConfigStatus defines the observed state of TalosConfig
type TalosConfigStatus struct {
// Ready indicates the BootstrapData field is ready to be consumed
Expand Down
49 changes: 49 additions & 0 deletions api/v1alpha3/talosconfig_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,60 @@
package v1alpha3

import (
"fmt"

apierrors "k8s.io/apimachinery/pkg/api/errors"
runtime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/validation/field"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/webhook"
)

func (r *TalosConfig) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
Complete()
}

//+kubebuilder:webhook:verbs=create;update;delete,path=/validate-bootstrap-cluster-x-k8s-io-v1alpha3-talosconfig,mutating=false,failurePolicy=fail,groups=bootstrap.cluster.x-k8s.io,resources=talosconfigs,versions=v1alpha3,name=vtalosconfig.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1

var _ webhook.Validator = &TalosConfig{}

// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (r *TalosConfig) ValidateCreate() error {
return r.validate()
}

// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (r *TalosConfig) ValidateUpdate(old runtime.Object) error {
return r.validate()
}

// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (r *TalosConfig) ValidateDelete() error {
return nil
}

func (r *TalosConfig) validate() error {
var allErrs field.ErrorList

switch r.Spec.Hostname.Source {
case "":
case HostnameSourceMachineName:
default:
allErrs = append(allErrs,
field.Invalid(field.NewPath("spec").Child("hostname").Child("source"), r.Spec.Hostname.Source,
fmt.Sprintf("valid values are: %q", []HostnameSource{HostnameSourceMachineName}),
),
)
}

if len(allErrs) == 0 {
return nil
}

return apierrors.NewInvalid(
schema.GroupKind{Group: GroupVersion.Group, Kind: "TalosConfig"},
r.Name, allErrs)
}
18 changes: 17 additions & 1 deletion api/v1alpha3/zz_generated.deepcopy.go

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

8 changes: 8 additions & 0 deletions config/crd/bases/bootstrap.cluster.x-k8s.io_talosconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,14 @@ spec:
type: string
generateType:
type: string
hostname:
description: Set hostname in the machine configuration to some value.
properties:
source:
description: "Source of the hostname. \n Allowed values: \"MachineName\"
(use linked Machine's Name)."
type: string
type: object
talosVersion:
type: string
required:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ spec:
type: string
generateType:
type: string
hostname:
description: Set hostname in the machine configuration to
some value.
properties:
source:
description: "Source of the hostname. \n Allowed values:
\"MachineName\" (use linked Machine's Name)."
type: string
type: object
talosVersion:
type: string
required:
Expand Down
12 changes: 5 additions & 7 deletions config/webhook/manifests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,13 @@ metadata:
webhooks:
- admissionReviewVersions:
- v1
- v1beta1
clientConfig:
caBundle: Cg==
service:
name: webhook-service
namespace: system
path: /validate-infrastructure-cluster-x-k8s-io-v1alpha3-talosconfig
path: /validate-bootstrap-cluster-x-k8s-io-v1alpha3-talosconfig
failurePolicy: Fail
matchPolicy: Equivalent
name: validation.talosconfig.bootstrap.cluster.x-k8s.io
name: vtalosconfig.cluster.x-k8s.io
rules:
- apiGroups:
- bootstrap.cluster.x-k8s.io
Expand All @@ -26,6 +23,7 @@ webhooks:
operations:
- CREATE
- UPDATE
- DELETE
resources:
- talosconfig
sideEffects: None
- talosconfigs
sideEffects: None
15 changes: 12 additions & 3 deletions controllers/talosconfig_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/source"

"github.com/talos-systems/cluster-api-bootstrap-provider-talos/api/v1alpha3"
bootstrapv1alpha3 "github.com/talos-systems/cluster-api-bootstrap-provider-talos/api/v1alpha3"
// +kubebuilder:scaffold:imports
)
Expand Down Expand Up @@ -463,7 +464,7 @@ func (r *TalosConfigReconciler) genConfigs(ctx context.Context, scope *TalosConf
}

clusterDNS := constants.DefaultDNSDomain
if scope.Cluster.Spec.ClusterNetwork.ServiceDomain != "" {
if scope.Cluster.Spec.ClusterNetwork != nil && scope.Cluster.Spec.ClusterNetwork.ServiceDomain != "" {
clusterDNS = scope.Cluster.Spec.ClusterNetwork.ServiceDomain
}

Expand Down Expand Up @@ -516,13 +517,21 @@ func (r *TalosConfigReconciler) genConfigs(ctx context.Context, scope *TalosConf
return retBundle, err
}

if scope.Cluster.Spec.ClusterNetwork.Pods != nil {
if scope.Cluster.Spec.ClusterNetwork != nil && scope.Cluster.Spec.ClusterNetwork.Pods != nil {
data.ClusterConfig.ClusterNetwork.PodSubnet = scope.Cluster.Spec.ClusterNetwork.Pods.CIDRBlocks
}
if scope.Cluster.Spec.ClusterNetwork.Services != nil {
if scope.Cluster.Spec.ClusterNetwork != nil && scope.Cluster.Spec.ClusterNetwork.Services != nil {
data.ClusterConfig.ClusterNetwork.ServiceSubnet = scope.Cluster.Spec.ClusterNetwork.Services.CIDRBlocks
}

if !scope.ConfigOwner.IsMachinePool() && scope.Config.Spec.Hostname.Source == v1alpha3.HostnameSourceMachineName {
if data.MachineConfig.MachineNetwork == nil {
data.MachineConfig.MachineNetwork = &v1alpha1.NetworkConfig{}
}

data.MachineConfig.MachineNetwork.NetworkHostname = scope.ConfigOwner.GetName()
}

dataOut, err := data.String()
if err != nil {
return retBundle, err
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ require (
k8s.io/apiextensions-apiserver v0.22.2
k8s.io/apimachinery v0.22.2
k8s.io/client-go v0.22.2
sigs.k8s.io/cluster-api v1.0.0
sigs.k8s.io/controller-runtime v0.10.2
sigs.k8s.io/cluster-api v1.0.3
sigs.k8s.io/controller-runtime v0.10.3
)

require (
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1216,10 +1216,10 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
sigs.k8s.io/cluster-api v1.0.0 h1:GcVA2ObQTXo/+jzSLWPy4Bd3NeiwJyAB8n19kyJIotA=
sigs.k8s.io/cluster-api v1.0.0/go.mod h1:V230kMSaYENTUcx1QRkoRCklb3vfphQGV3/z4ODNGWo=
sigs.k8s.io/controller-runtime v0.10.2 h1:jW8qiY+yMnnPx6O9hu63tgcwaKzd1yLYui+mpvClOOc=
sigs.k8s.io/controller-runtime v0.10.2/go.mod h1:CQp8eyUQZ/Q7PJvnIrB6/hgfTC1kBkGylwsLgOQi1WY=
sigs.k8s.io/cluster-api v1.0.3 h1:unJqMUG5LJ312kgHSAnBzfYazbGCcGkTcdGD3lF459k=
sigs.k8s.io/cluster-api v1.0.3/go.mod h1:/LkJXtsvhxTV4U0z1Y2Y1Gr2xebJ0/ce09Ab2M0XU/U=
sigs.k8s.io/controller-runtime v0.10.3 h1:s5Ttmw/B4AuIbwrXD3sfBkXwnPMMWrqpVj4WRt1dano=
sigs.k8s.io/controller-runtime v0.10.3/go.mod h1:CQp8eyUQZ/Q7PJvnIrB6/hgfTC1kBkGylwsLgOQi1WY=
sigs.k8s.io/kustomize/api v0.8.11/go.mod h1:a77Ls36JdfCWojpUqR6m60pdGY1AYFix4AH83nJtY1g=
sigs.k8s.io/kustomize/cmd/config v0.9.13/go.mod h1:7547FLF8W/lTaDf0BDqFTbZxM9zqwEJqCKN9sSR0xSs=
sigs.k8s.io/kustomize/kustomize/v4 v4.2.0/go.mod h1:MOkR6fmhwG7hEDRXBYELTi5GSFcLwfqwzTRHW3kv5go=
Expand Down
3 changes: 3 additions & 0 deletions hack/clusterctl.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# temporary, see https://github.com/kubernetes-sigs/cluster-api/issues/6051
cert-manager:
url: "https://github.com/cert-manager/cert-manager/releases/latest/cert-manager.yaml"
4 changes: 2 additions & 2 deletions internal/integration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Bring up Talos cluster (or any other Kubernetes clusters).

Put `kubeconfig` to the root of the repository (for Talos: `talosctl -n <IP> kubeconfig -f kubeconfig`).

Create release with fixed tag: `make release-manifests TAG=v0.4.0` (update release if the CRDs are updated).
Create release with fixed tag: `make release-manifests TAG=v0.5.0` (update release if the CRDs are updated).

Run tests: `make test TAG=v0.4.0`.
Run tests: `make test TAG=v0.5.0`.

Tests clean up after the run, so they can be run repeatedly against the cluster.
47 changes: 47 additions & 0 deletions internal/integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"inet.af/netaddr"
corev1 "k8s.io/api/core/v1"
apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
capiv1 "sigs.k8s.io/cluster-api/api/v1beta1"
Expand Down Expand Up @@ -437,6 +438,52 @@ func TestIntegration(t *testing.T) {
"failure applying rfc6902 patches to talos machine config: add operation does not apply: doc is missing path: \"/machine/time/servers\": missing value",
conditions.GetMessage(talosConfig, bootstrapv1alpha3.DataSecretAvailableCondition))
})
t.Run("HostnameFromMachineName", func(t *testing.T) {
t.Parallel()

namespaceName := setupTest(ctx, t, c)
cluster := createCluster(ctx, t, c, namespaceName, &capiv1.ClusterSpec{
ControlPlaneEndpoint: capiv1.APIEndpoint{
Host: "example.com",
Port: 443,
},
}, true)
talosConfig := createTalosConfig(ctx, t, c, namespaceName, bootstrapv1alpha3.TalosConfigSpec{
GenerateType: talosmachine.TypeControlPlane.String(),
TalosVersion: TalosVersion,
Hostname: bootstrapv1alpha3.HostnameSpec{
Source: bootstrapv1alpha3.HostnameSourceMachineName,
},
})
machine := createMachine(ctx, t, c, cluster, talosConfig, true)
waitForReady(ctx, t, c, talosConfig)

provider := assertMachineConfiguration(ctx, t, c, talosConfig)

assert.Equal(t, machine.Name, provider.Machine().Network().Hostname())
})
t.Run("TalosConfigValidate", func(t *testing.T) {
t.Parallel()

namespaceName := setupTest(ctx, t, c)

talosConfigName := generateName(t, "talosconfig")
talosConfig := &bootstrapv1alpha3.TalosConfig{
ObjectMeta: metav1.ObjectMeta{
Namespace: namespaceName,
Name: talosConfigName,
},
Spec: bootstrapv1alpha3.TalosConfigSpec{
Hostname: bootstrapv1alpha3.HostnameSpec{
Source: "foo",
},
},
}

err := c.Create(ctx, talosConfig)
require.Error(t, err)
assert.True(t, apierrors.IsInvalid(err))
})
}

// legacy cluster secret format
Expand Down
Loading

0 comments on commit c7a7265

Please sign in to comment.