Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🌱 flavor-gen: bump CPI manifests and use embed instead of hardcoding #2625

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
333 changes: 51 additions & 282 deletions packaging/flavorgen/cloudprovider/cloud-controller-manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ limitations under the License.
package cloudprovider

import (
"fmt"
"errors"
"regexp"
"strings"

appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"sigs.k8s.io/yaml"

"sigs.k8s.io/cluster-api-provider-vsphere/packaging/flavorgen/flavors/env"
)
Expand All @@ -35,295 +35,64 @@ const (
CPIControllerImageURL = "gcr.io/cloud-provider-vsphere/cpi/release/manager"
)

// CloudControllerManagerServiceAccount returns the ServiceAccount used for the cloud-controller-manager.
func CloudControllerManagerServiceAccount() *corev1.ServiceAccount {
return &corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Name: "cloud-controller-manager",
Namespace: "kube-system",
},
TypeMeta: metav1.TypeMeta{
Kind: "ServiceAccount",
APIVersion: corev1.SchemeGroupVersion.String(),
},
// CloudControllerManagerManifests returns the yaml manifests generated via
// `helm template` from https://github.com/kubernetes/cloud-provider-vsphere/tree/master/charts/vsphere-cpi
func CloudControllerManagerManifests() (string, error) {
objectList := []string{}

// Replace the hardcoded image tag by a variable for clusterctl. This way we can dynamically configure the version of CPI.
imageTagRemoval := regexp.MustCompile(`(image: .*):.*`)
sbueringer marked this conversation as resolved.
Show resolved Hide resolved
withoutTag := imageTagRemoval.ReplaceAll([]byte(cpiManifests), []byte(`${1}:$`+env.CPIImageKubernetesVersionVar))

// ClusterResourceSet does not support `kind: List`, we have to adjust the manifests
// to remove those lists and directly add the items instead.
sbueringer marked this conversation as resolved.
Show resolved Hide resolved
for _, object := range strings.Split(string(withoutTag), "---\n") {
// Ignore empty strings
if object == "" {
continue
}
// Marshal to unstructured so we can check the type
u := &unstructured.Unstructured{}
if err := yaml.Unmarshal([]byte(object), u); err != nil {
return "", err
}
// If it is not a List we can directly add the object to the slice
if u.GetKind() != "List" {
objectList = append(objectList, object)
continue
}

// If it is a list we extract the slice at `items`
items, isSlice, err := unstructured.NestedSlice(u.UnstructuredContent(), "items")
if err != nil {
return "", err
}
if !isSlice {
return "", errors.New("expected List.items to be a slice")
}

// Loop over all items, marshal them and add it to objects.
for _, item := range items {
marshaledItem, err := yaml.Marshal(item)
if err != nil {
return "", err
}
objectList = append(objectList, string(marshaledItem))
}
}
}

// CloudControllerManagerService returns a Service for the cloud-controller-manager.
func CloudControllerManagerService() *corev1.Service {
return &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "cloud-controller-manager",
Namespace: "kube-system",
Labels: map[string]string{
"component": "cloud-controller-manager",
},
},
Spec: corev1.ServiceSpec{
Type: corev1.ServiceTypeNodePort,
Ports: []corev1.ServicePort{
{
Port: 443,
Protocol: corev1.ProtocolTCP,
TargetPort: intstr.FromInt(43001),
},
},
Selector: map[string]string{
"component": "cloud-controller-manager",
},
},
}
return "---\n" + strings.Join(objectList, "---\n"), nil
}

// CloudControllerManagerConfigMap returns a ConfigMap containing data for the cloud config file.
func CloudControllerManagerConfigMap(cloudConfig string) *corev1.ConfigMap {
return &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "vsphere-cloud-config",
Name: "cloud-config",
sbueringer marked this conversation as resolved.
Show resolved Hide resolved
Namespace: "kube-system",
},
Data: map[string]string{
"vsphere.conf": cloudConfig,
},
}
}

// CloudControllerManagerDaemonSet returns the DaemonSet which runs the cloud-controller-manager.
func CloudControllerManagerDaemonSet(args []string) *appsv1.DaemonSet {
return &appsv1.DaemonSet{
ObjectMeta: metav1.ObjectMeta{
Name: "vsphere-cloud-controller-manager",
Namespace: "kube-system",
Labels: map[string]string{
"component": "cloud-controller-manager",
"tier": "control-plane",
},
},
Spec: appsv1.DaemonSetSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"name": "vsphere-cloud-controller-manager",
},
},
UpdateStrategy: appsv1.DaemonSetUpdateStrategy{
Type: appsv1.RollingUpdateDaemonSetStrategyType,
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"name": "vsphere-cloud-controller-manager",
"component": "cloud-controller-manager",
"tier": "control-plane",
},
},
Spec: corev1.PodSpec{
SecurityContext: &corev1.PodSecurityContext{
RunAsUser: int64ptr(1001),
},
Tolerations: []corev1.Toleration{
{
Key: "node.cloudprovider.kubernetes.io/uninitialized",
Value: "true",
Effect: corev1.TaintEffectNoSchedule,
},
{
Key: "node-role.kubernetes.io/master",
Effect: corev1.TaintEffectNoSchedule,
Operator: corev1.TolerationOpExists,
},
{
Key: "node-role.kubernetes.io/control-plane",
Effect: corev1.TaintEffectNoSchedule,
Operator: corev1.TolerationOpExists,
},
{
Key: "node.kubernetes.io/not-ready",
Effect: corev1.TaintEffectNoSchedule,
Operator: corev1.TolerationOpExists,
},
},
ServiceAccountName: "cloud-controller-manager",
PriorityClassName: "system-node-critical",
Containers: []corev1.Container{
{
Name: "vsphere-cloud-controller-manager",
Image: fmt.Sprintf("%s:%s", CPIControllerImageURL, env.CPIImageKubernetesVersionVar),
Args: args,
VolumeMounts: []corev1.VolumeMount{
{
Name: "vsphere-config-volume",
MountPath: "/etc/cloud",
ReadOnly: true,
},
},
Resources: corev1.ResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("200m"),
},
},
},
},
HostNetwork: true,
Volumes: []corev1.Volume{
{
Name: "vsphere-config-volume",
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: "vsphere-cloud-config",
},
},
},
},
},
Affinity: &corev1.Affinity{
NodeAffinity: &corev1.NodeAffinity{
RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
NodeSelectorTerms: []corev1.NodeSelectorTerm{
{
MatchExpressions: []corev1.NodeSelectorRequirement{
{
Key: "node-role.kubernetes.io/control-plane",
Operator: corev1.NodeSelectorOpExists,
},
},
},
{
MatchExpressions: []corev1.NodeSelectorRequirement{
{
Key: "node-role.kubernetes.io/master",
Operator: corev1.NodeSelectorOpExists,
},
},
},
},
},
},
},
},
},
},
}
}

// CloudControllerManagerClusterRole returns the ClusterRole systemLcloud-controller-manager
// used by the cloud-controller-manager.
func CloudControllerManagerClusterRole() *rbacv1.ClusterRole {
return &rbacv1.ClusterRole{
ObjectMeta: metav1.ObjectMeta{
Name: "system:cloud-controller-manager",
},
Rules: []rbacv1.PolicyRule{
{
APIGroups: []string{""},
Resources: []string{"events"},
Verbs: []string{"create", "patch", "update"},
},
{
APIGroups: []string{""},
Resources: []string{"nodes"},
Verbs: []string{"*"},
},
{
APIGroups: []string{""},
Resources: []string{"nodes/status"},
Verbs: []string{"patch"},
},
{
APIGroups: []string{""},
Resources: []string{"services"},
Verbs: []string{"list", "patch", "update", "watch"},
},
{
APIGroups: []string{""},
Resources: []string{"services/status"},
Verbs: []string{"patch"},
},
{
APIGroups: []string{""},
Resources: []string{"serviceaccounts"},
Verbs: []string{"create", "get", "list", "watch", "update"},
},
{
APIGroups: []string{""},
Resources: []string{"persistentvolumes"},
Verbs: []string{"get", "list", "watch", "update"},
},
{
APIGroups: []string{""},
Resources: []string{"endpoints"},
Verbs: []string{"create", "get", "list", "watch", "update"},
},
{
APIGroups: []string{""},
Resources: []string{"secrets"},
Verbs: []string{"get", "list", "watch"},
},
{
APIGroups: []string{"coordination.k8s.io"},
Resources: []string{"leases"},
Verbs: []string{"get", "watch", "list", "update", "create"},
},
},
}
}

// CloudControllerManagerRoleBinding binds the extension-apiserver-authentication-reader
// to the cloud-controller-manager.
func CloudControllerManagerRoleBinding() *rbacv1.RoleBinding {
return &rbacv1.RoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "servicecatalog.k8s.io:apiserver-authentication-reader",
Namespace: "kube-system",
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "Role",
Name: "extension-apiserver-authentication-reader",
},
Subjects: []rbacv1.Subject{
{
APIGroup: "",
Kind: "ServiceAccount",
Name: "cloud-controller-manager",
Namespace: "kube-system",
},
{
APIGroup: "",
Kind: "User",
Name: "cloud-controller-manager",
},
},
}
}

// CloudControllerManagerClusterRoleBinding binds the system:cloud-controller-manager
// cluster role to the cloud-controller-manager.
func CloudControllerManagerClusterRoleBinding() *rbacv1.ClusterRoleBinding {
return &rbacv1.ClusterRoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "system:cloud-controller-manager",
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "ClusterRole",
Name: "system:cloud-controller-manager",
},
Subjects: []rbacv1.Subject{
{
Kind: "ServiceAccount",
Name: "cloud-controller-manager",
Namespace: "kube-system",
},
{
Kind: "User",
Name: "cloud-controller-manager",
},
},
}
}

func int64ptr(i int) *int64 {
ptr := int64(i)
return &ptr
}
Loading
Loading