1
0
mirror of https://github.com/rancher/os.git synced 2025-09-08 18:20:32 +00:00

Add operator

This commit is contained in:
Darren Shepherd
2021-10-20 10:58:54 -07:00
parent 0e46d19194
commit 5675644d9f
60 changed files with 5387 additions and 60 deletions

View File

@@ -0,0 +1,80 @@
package inventory
import (
"context"
"fmt"
v1 "github.com/rancher/os/pkg/apis/rancheros.cattle.io/v1"
"github.com/rancher/os/pkg/clients"
ranchercontrollers "github.com/rancher/os/pkg/generated/controllers/management.cattle.io/v3"
provcontrollers "github.com/rancher/os/pkg/generated/controllers/provisioning.cattle.io/v1"
v12 "github.com/rancher/os/pkg/generated/controllers/rancheros.cattle.io/v1"
v3 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3"
"github.com/rancher/wrangler/pkg/name"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type handler struct {
clusterCache provcontrollers.ClusterCache
clusterRegistrationTokenCache ranchercontrollers.ClusterRegistrationTokenCache
clusterRegistrationTokenClient ranchercontrollers.ClusterRegistrationTokenClient
}
func Register(ctx context.Context, clients *clients.Clients) {
h := &handler{
clusterCache: clients.Provisioning.Cluster().Cache(),
clusterRegistrationTokenCache: clients.Rancher.ClusterRegistrationToken().Cache(),
clusterRegistrationTokenClient: clients.Rancher.ClusterRegistrationToken(),
}
clients.OS.MachineInventory().OnRemove(ctx, "machine-inventory-remove", h.OnMachineInventoryRemove)
v12.RegisterMachineInventoryStatusHandler(ctx, clients.OS.MachineInventory(), "", "machine-inventory", h.OnMachineInventory)
}
func (h *handler) OnMachineInventoryRemove(key string, machine *v1.MachineInventory) (*v1.MachineInventory, error) {
if machine.Status.ClusterRegistrationTokenName != "" && machine.Status.ClusterRegistrationTokenNamespace != "" {
err := h.clusterRegistrationTokenClient.Delete(machine.Status.ClusterRegistrationTokenNamespace, machine.Status.ClusterRegistrationTokenName, nil)
if !apierrors.IsNotFound(err) && err != nil {
return nil, err
}
}
return machine, nil
}
func (h *handler) OnMachineInventory(machine *v1.MachineInventory, status v1.MachineInventoryStatus) (v1.MachineInventoryStatus, error) {
if machine == nil {
return status, nil
}
cluster, err := h.clusterCache.Get(machine.Namespace, machine.Spec.ClusterName)
if err != nil {
return status, err
}
if cluster.Status.ClusterName == "" {
return status, fmt.Errorf("waiting for mgmt cluster to be created for prov cluster %s/%s", machine.Namespace, machine.Spec.ClusterName)
}
crtName := name.SafeConcatName(cluster.Status.ClusterName, machine.Name, "-token")
_, err = h.clusterRegistrationTokenCache.Get(cluster.Status.ClusterName, crtName)
if apierrors.IsNotFound(err) {
_, err = h.clusterRegistrationTokenClient.Create(&v3.ClusterRegistrationToken{
ObjectMeta: metav1.ObjectMeta{
Name: crtName,
Namespace: cluster.Status.ClusterName,
},
Spec: v3.ClusterRegistrationTokenSpec{
ClusterName: cluster.Status.ClusterName,
},
})
}
if err != nil {
return status, err
}
status.ClusterRegistrationTokenName = crtName
status.ClusterRegistrationTokenNamespace = cluster.Status.ClusterName
return status, nil
}

View File

@@ -0,0 +1,104 @@
package managedos
import (
"context"
"github.com/rancher/fleet/pkg/apis/fleet.cattle.io/v1alpha1"
provv1 "github.com/rancher/os/pkg/apis/rancheros.cattle.io/v1"
"github.com/rancher/os/pkg/clients"
fleetcontrollers "github.com/rancher/os/pkg/generated/controllers/fleet.cattle.io/v1alpha1"
ranchercontrollers "github.com/rancher/os/pkg/generated/controllers/management.cattle.io/v3"
oscontrollers "github.com/rancher/os/pkg/generated/controllers/rancheros.cattle.io/v1"
"github.com/rancher/wrangler/pkg/name"
"github.com/rancher/wrangler/pkg/relatedresource"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
func Register(ctx context.Context, clients *clients.Clients) {
h := &handler{
bundleCache: clients.Fleet.Bundle().Cache(),
settingsCache: clients.Rancher.Setting().Cache(),
}
relatedresource.Watch(ctx,
"mcc-from-bundle-trigger",
relatedresource.OwnerResolver(true, provv1.SchemeGroupVersion.String(), "ManagedOSImage"),
clients.OS.ManagedOSImage(),
clients.Fleet.Bundle())
oscontrollers.RegisterManagedOSImageGeneratingHandler(ctx,
clients.OS.ManagedOSImage(),
clients.Apply.
WithSetOwnerReference(true, true).
WithCacheTypes(
clients.OS.ManagedOSImage(),
clients.Fleet.Bundle()),
"Defined",
"mos-bundle",
h.OnChange,
nil)
}
type handler struct {
bundleCache fleetcontrollers.BundleCache
settingsCache ranchercontrollers.SettingCache
}
func (h *handler) defaultRegistry() (string, error) {
setting, err := h.settingsCache.Get("system-default-registry")
if err != nil {
return "", err
}
if setting.Value == "" {
return setting.Default, nil
}
return setting.Value, nil
}
func (h *handler) OnChange(mos *provv1.ManagedOSImage, status provv1.ManagedOSImageStatus) ([]runtime.Object, provv1.ManagedOSImageStatus, error) {
if mos.Spec.OSImage == "" {
return nil, status, nil
}
prefix, err := h.defaultRegistry()
if err != nil {
return nil, status, err
}
resources, err := ToResources(objects(mos, prefix))
if err != nil {
return nil, status, err
}
bundle := &v1alpha1.Bundle{
ObjectMeta: metav1.ObjectMeta{
Name: name.SafeConcatName("mos", mos.Name),
Namespace: mos.Namespace,
},
Spec: v1alpha1.BundleSpec{
Resources: resources,
BundleDeploymentOptions: v1alpha1.BundleDeploymentOptions{},
Paused: mos.Spec.Paused,
RolloutStrategy: mos.Spec.ClusterRolloutStrategy,
Targets: mos.Spec.Targets,
},
}
status, err = h.updateStatus(status, bundle)
return []runtime.Object{
bundle,
}, status, err
}
func (h *handler) updateStatus(status provv1.ManagedOSImageStatus, bundle *v1alpha1.Bundle) (provv1.ManagedOSImageStatus, error) {
bundle, err := h.bundleCache.Get(bundle.Namespace, bundle.Name)
if apierrors.IsNotFound(err) {
return status, nil
} else if err != nil {
return status, err
}
status.BundleStatus = bundle.Status
return status, nil
}

View File

@@ -0,0 +1,46 @@
package managedos
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/rancher/fleet/pkg/apis/fleet.cattle.io/v1alpha1"
"github.com/rancher/wrangler/pkg/gvk"
"github.com/rancher/wrangler/pkg/name"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
)
func ToResources(objs []runtime.Object) (result []v1alpha1.BundleResource, err error) {
for _, obj := range objs {
obj = obj.DeepCopyObject()
if err := gvk.Set(obj); err != nil {
return nil, fmt.Errorf("failed to set gvk: %w", err)
}
typeMeta, err := meta.TypeAccessor(obj)
if err != nil {
return nil, err
}
meta, err := meta.Accessor(obj)
if err != nil {
return nil, err
}
data, err := json.Marshal(obj)
if err != nil {
return nil, err
}
digest := sha256.Sum256(data)
filename := name.SafeConcatName(typeMeta.GetKind(), meta.GetNamespace(), meta.GetName(), hex.EncodeToString(digest[:])[:12]) + ".yaml"
result = append(result, v1alpha1.BundleResource{
Name: filename,
Content: string(data),
})
}
return
}

View File

@@ -0,0 +1,105 @@
package managedos
import (
"strings"
osv1 "github.com/rancher/os/pkg/apis/rancheros.cattle.io/v1"
"github.com/rancher/os/pkg/clients"
upgradev1 "github.com/rancher/system-upgrade-controller/pkg/apis/upgrade.cattle.io/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
func objects(mos *osv1.ManagedOSImage, prefix string) []runtime.Object {
concurrency := int64(1)
if mos.Spec.Concurrency != nil {
concurrency = *mos.Spec.Concurrency
}
cordon := true
if mos.Spec.Cordon != nil {
cordon = *mos.Spec.Cordon
}
image := strings.SplitN(mos.Spec.OSImage, ":", 2)
version := "latest"
if len(image) == 2 {
version = image[1]
}
selector := mos.Spec.NodeSelector
if selector == nil {
selector = &metav1.LabelSelector{}
}
return []runtime.Object{
&rbacv1.ClusterRole{
ObjectMeta: metav1.ObjectMeta{
Name: "os-upgrader",
},
Rules: []rbacv1.PolicyRule{{
Verbs: []string{"update", "get", "list", "watch", "patch"},
APIGroups: []string{""},
Resources: []string{"nodes"},
}},
},
&rbacv1.ClusterRoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "os-upgrader",
},
Subjects: []rbacv1.Subject{{
Kind: "ServiceAccount",
Name: "os-upgrader",
Namespace: clients.SystemNamespace,
}},
RoleRef: rbacv1.RoleRef{
APIGroup: rbacv1.GroupName,
Kind: "ClusterRole",
Name: "os-upgrader",
},
},
&corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Name: "os-upgrader",
Namespace: clients.SystemNamespace,
},
},
&upgradev1.Plan{
TypeMeta: metav1.TypeMeta{
Kind: "Plan",
APIVersion: "upgrade.cattle.io/v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "os-upgrader",
Namespace: clients.SystemNamespace,
},
Spec: upgradev1.PlanSpec{
Concurrency: concurrency,
Version: version,
Tolerations: []corev1.Toleration{{
Operator: corev1.TolerationOpExists,
}},
ServiceAccountName: "os-upgrader",
NodeSelector: selector,
Cordon: cordon,
Drain: mos.Spec.Drain,
Prepare: mos.Spec.Prepare,
Upgrade: &upgradev1.ContainerSpec{
Image: PrefixPrivateRegistry(image[0], prefix),
Command: []string{
"/usr/sbin/suc-upgrade",
},
},
},
},
}
}
func PrefixPrivateRegistry(image, prefix string) string {
if prefix == "" {
return image
}
return prefix + "/" + image
}