Skip to content

Commit

Permalink
Added: support for adding labels from the config itself
Browse files Browse the repository at this point in the history
  • Loading branch information
yashvardhan-kukreja committed Nov 13, 2020
1 parent e7d1a7d commit b7cf15a
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 0 deletions.
3 changes: 3 additions & 0 deletions pkg/apis/config/v1alpha4/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ type Node struct {
// If unset a default image will be used, see defaults.Image
Image string `yaml:"image,omitempty"`

// Labels are the labels with which the respective node will be labeled
Labels map[string]string `yaml:"labels,omitempty"`

/* Advanced fields */

// TODO: cri-like types should be inline instead
Expand Down
7 changes: 7 additions & 0 deletions pkg/apis/config/v1alpha4/zz_generated.deepcopy.go

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
Copyright 2019 The Kubernetes Authors.
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 postcreationconfiguration implements the action for configuring cluster after cluster creation
// like labelling, tainting, etc the nodes.
package postcreationconfiguration

import (
"fmt"
"strings"

"sigs.k8s.io/kind/pkg/cluster/internal/create/actions"
"sigs.k8s.io/kind/pkg/cluster/nodes"
"sigs.k8s.io/kind/pkg/cluster/nodeutils"
"sigs.k8s.io/kind/pkg/internal/apis/config"
)

// Action implements and action for configuring the cluster after cluster creation
type Action struct{}

// NewAction returns a new Action for configuring the cluster after cluster creation
func NewAction() actions.Action {
return &Action{}
}

// Execute runs the action
func (a *Action) Execute(ctx *actions.ActionContext) error {

// Label the control-plane and worker nodes as per the config file
if err := labelNodes(ctx); err != nil {
return err
}

return nil
}

// labelNodes labels the control-plane and worker nodes
// as per the labels provided in the config file
func labelNodes(ctx *actions.ActionContext) error {
allNodes, err := ctx.Nodes()
if err != nil {
return err
}

// Get one of the cluster nodes for the execution of labelling action/command.
// The labelling action/command for a control-plane node will be executed by that respective node only. (label will be self-applied for the control-plane node)
// The labelling action/command for a worker node will be executed by the below 'firstControlPlane' node.
controlPlanes, err := nodeutils.ControlPlaneNodes(allNodes)
if err != nil {
return err
}
firstControlPlaneNode := controlPlanes[0]

// Populate the list of control-plane node labels and the list of worker node labels respectively.
// controlPlaneLabels is an array of maps (labels, read from config) associated with all the control-plane nodes.
// workerLabels is an array of maps (labels, read from config) associated with all the worker nodes.
controlPlaneLabels := []map[string]string{}
workerLabels := []map[string]string{}
for _, node := range ctx.Config.Nodes {
if node.Role == config.ControlPlaneRole {
controlPlaneLabels = append(controlPlaneLabels, node.Labels)
} else if node.Role == config.WorkerRole {
workerLabels = append(workerLabels, node.Labels)
} else {
continue
}
}

// Label the control-plane and worker nodes accordingly.
controlPlaneLabelsCounter := 0
workerLabelsCounter := 0
for _, node := range allNodes {
nodeName := node.String()
nodeRole, err := node.Role()
if err != nil {
return err
}

var currentNodeLabels map[string]string
var cmdExecutorNode nodes.Node
if nodeRole == string(config.ControlPlaneRole) {
cmdExecutorNode = node
currentNodeLabels = controlPlaneLabels[controlPlaneLabelsCounter]
controlPlaneLabelsCounter++
} else if nodeRole == string(config.WorkerRole) {
cmdExecutorNode = firstControlPlaneNode
currentNodeLabels = workerLabels[workerLabelsCounter]
workerLabelsCounter++
} else {
continue
}
if len(currentNodeLabels) == 0 {
continue
}

// Construct the `kubectl label` command as per the current labels for the current node in the loop.
labelCommandArgsStr := fmt.Sprintf("--kubeconfig=/etc/kubernetes/admin.conf label node %s ", nodeName)
for key, value := range currentNodeLabels {
labelCommandArgsStr += fmt.Sprintf("%s=%s ", key, value)
}
labelCommandArgs := strings.Split(strings.TrimSpace(labelCommandArgsStr), " ")

// Execute the constructed `kubectl load` command via the rightful node
// If the labels are being applied to a control-plane node, then, it will be self-applied by that node
// If the labels are being applied to a worker node, then, it will be applied a control-plane node ('firstControlPlaneNode')
if err := cmdExecutorNode.Command("kubectl", labelCommandArgs...).Run(); err != nil {
return err
}
}

return nil
}
2 changes: 2 additions & 0 deletions pkg/cluster/internal/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
"sigs.k8s.io/kind/pkg/cluster/internal/create/actions/kubeadminit"
"sigs.k8s.io/kind/pkg/cluster/internal/create/actions/kubeadmjoin"
"sigs.k8s.io/kind/pkg/cluster/internal/create/actions/loadbalancer"
"sigs.k8s.io/kind/pkg/cluster/internal/create/actions/postcreationconfiguration"
"sigs.k8s.io/kind/pkg/cluster/internal/create/actions/waitforready"
"sigs.k8s.io/kind/pkg/cluster/internal/kubeconfig"
)
Expand Down Expand Up @@ -136,6 +137,7 @@ func Cluster(logger log.Logger, p providers.Provider, opts *ClusterOptions) erro
installstorage.NewAction(), // install StorageClass
kubeadmjoin.NewAction(), // run kubeadm join
waitforready.NewAction(opts.WaitForReady), // wait for cluster readiness
postcreationconfiguration.NewAction(), // perform post-cluster-creation configurations like custom labelling, tainting, etc.
)
}

Expand Down
1 change: 1 addition & 0 deletions pkg/internal/apis/config/convert_v1alpha4.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ func convertv1alpha4Node(in *v1alpha4.Node, out *Node) {
out.Role = NodeRole(in.Role)
out.Image = in.Image

out.Labels = in.Labels
out.KubeadmConfigPatches = in.KubeadmConfigPatches
out.ExtraMounts = make([]Mount, len(in.ExtraMounts))
out.ExtraPortMappings = make([]PortMapping, len(in.ExtraPortMappings))
Expand Down
3 changes: 3 additions & 0 deletions pkg/internal/apis/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ type Node struct {
// If unset a default image will be used, see defaults.Image
Image string

// Labels are the labels with which the respective node will be labeled
Labels map[string]string

/* Advanced fields */

// ExtraMounts describes additional mount points for the node container
Expand Down
7 changes: 7 additions & 0 deletions pkg/internal/apis/config/zz_generated.deepcopy.go

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

0 comments on commit b7cf15a

Please sign in to comment.