Skip to content

Commit

Permalink
breaking: remove support for packet-ccm
Browse files Browse the repository at this point in the history
Signed-off-by: Chris Privitere <23177737+cprivitere@users.noreply.github.com>
  • Loading branch information
cprivitere committed Dec 6, 2023
1 parent 86a311d commit 7d01003
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 657 deletions.
5 changes: 2 additions & 3 deletions config/manager/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,10 @@ spec:
port: healthz
resources:
limits:
cpu: 100m
memory: 50Mi
memory: 200Mi
requests:
cpu: 100m
memory: 35Mi
memory: 200Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
Expand Down
15 changes: 8 additions & 7 deletions controllers/packetmachine_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,14 @@ func (r *PacketMachineReconciler) Reconcile(ctx context.Context, req ctrl.Reques

log.Info("Before the machine scope")
// Create the machine scope
machineScope, err := scope.NewMachineScope(ctx, scope.MachineScopeParams{
Client: r.Client,
Cluster: cluster,
Machine: machine,
PacketCluster: packetcluster,
PacketMachine: packetmachine,
})
machineScope, err := scope.NewMachineScope(
scope.MachineScopeParams{
Client: r.Client,
Cluster: cluster,
Machine: machine,
PacketCluster: packetcluster,
PacketMachine: packetmachine,
})
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to create scope: %w", err)
}
Expand Down
220 changes: 6 additions & 214 deletions pkg/cloud/packet/scope/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,12 @@ import (
"context"
"errors"
"fmt"
"net/url"
"strings"

appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/ptr"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1"
"sigs.k8s.io/cluster-api/controllers/noderefutil"
"sigs.k8s.io/cluster-api/controllers/remote"
capierrors "sigs.k8s.io/cluster-api/errors"
"sigs.k8s.io/cluster-api/util"
"sigs.k8s.io/cluster-api/util/conditions"
Expand All @@ -42,11 +35,6 @@ import (
infrav1 "sigs.k8s.io/cluster-api-provider-packet/api/v1beta1"
)

const (
providerIDPrefix = "equinixmetal"
deprecatedProviderIDPrefix = "packet"
)

var (
// ErrMissingClient is returned when a client is not provided to the MachineScope.
ErrMissingClient = errors.New("client is required when creating a MachineScope")
Expand All @@ -71,14 +59,12 @@ type MachineScopeParams struct {
Machine *clusterv1.Machine
PacketCluster *infrav1.PacketCluster
PacketMachine *infrav1.PacketMachine

workloadClientGetter remote.ClusterClientGetter
}

// NewMachineScope creates a new MachineScope from the supplied parameters.
// This is meant to be called for each reconcile iteration
// both PacketClusterReconciler and PacketMachineReconciler.
func NewMachineScope(ctx context.Context, params MachineScopeParams) (*MachineScope, error) {
func NewMachineScope(params MachineScopeParams) (*MachineScope, error) {
if params.Client == nil {
return nil, ErrMissingClient
}
Expand All @@ -95,21 +81,13 @@ func NewMachineScope(ctx context.Context, params MachineScopeParams) (*MachineSc
return nil, ErrMissingPacketMachine
}

providerIDPrefix, err := getProviderIDPrefix(ctx, params.Client, params.workloadClientGetter,
params.Cluster, params.Machine, params.PacketMachine)
if err != nil {
return nil, err
}

helper, err := patch.NewHelper(params.PacketMachine, params.Client)
if err != nil {
return nil, fmt.Errorf("failed to init patch helper: %w", err)
}
return &MachineScope{
client: params.Client,
patchHelper: helper,
providerIDPrefix: providerIDPrefix,

client: params.Client,
patchHelper: helper,
Cluster: params.Cluster,
Machine: params.Machine,
PacketCluster: params.PacketCluster,
Expand All @@ -119,10 +97,8 @@ func NewMachineScope(ctx context.Context, params MachineScopeParams) (*MachineSc

// MachineScope defines a scope defined around a machine and its cluster.
type MachineScope struct {
client client.Client
patchHelper *patch.Helper
providerIDPrefix string

client client.Client
patchHelper *patch.Helper
Cluster *clusterv1.Cluster
Machine *clusterv1.Machine
PacketCluster *infrav1.PacketCluster
Expand Down Expand Up @@ -167,7 +143,7 @@ func (m *MachineScope) GetProviderID() string {

// SetProviderID sets the DOMachine providerID in spec from device id.
func (m *MachineScope) SetProviderID(deviceID string) {
pid := fmt.Sprintf("%s://%s", m.providerIDPrefix, deviceID)
pid := fmt.Sprintf("%s://%s", "equinixmetal", deviceID)
m.PacketMachine.Spec.ProviderID = ptr.To(pid)
}

Expand Down Expand Up @@ -244,190 +220,6 @@ func (m *MachineScope) GetRawBootstrapData(ctx context.Context) ([]byte, error)
return value, nil
}

// getProviderIDPrefix attempts to determine what providerID prefix should be used for this PacketMachine based on the following precedence:
// - If the PacketMachine already has a providerID defined, use the prefix from that providerID
// - If the workload cluster is already responding, attempt to determine the prefix to use based on the cloud provider deployed
// - If the bootstrap provider being used is the KubeadmConfig bootstrap provider, attempt to determine the prefix to use based on the bootstrap configuration
// - Otherwise, default to using "equinixmetal" as the prefix
// This order is used, because the underlying Node providerIDs are immutable, so we should treat the PacketMachine providerIDs similarly.
// When the providerID has not already been set, we should always prioritize setting the providerID prefix to match the deployed version
// of the cloud-provider, if possible. This ensures that we set the providerID in a way that will match what is configured on the node by
// the cloud-provider. However, when the workload cluster is first being bootstrapped, we cannot access the (yet to be provisioned) api server
// to query the actively deployed cloud-provider, so we need to attempt to determine which cloud-provider will be deployed through the
// bootstrapping configuration. If we cannot determine the providerID through any of those means, then we should assume that
// cloud-provider-equinix-metal will be used and default to "equinixmetal" as the prefix.
func getProviderIDPrefix(ctx context.Context, mgmtClient client.Client, workloadClientGetter remote.ClusterClientGetter, cluster *clusterv1.Cluster, machine *clusterv1.Machine, packetMachine *infrav1.PacketMachine) (string, error) {
// Use existing prefix if already defined
if existingPrefix := providerIDPrefixFromPacketMachine(packetMachine); existingPrefix != "" {
return existingPrefix, nil
}

// Try to determine the appropriate prefix from any known cloud-provider deployments
fromDeployments, err := providerIDFromCloudProviderDeployments(ctx, mgmtClient, workloadClientGetter, cluster)
if err != nil {
return "", err
}
if fromDeployments != "" {
return fromDeployments, nil
}

// Try to determine the appropriate prefix from the KubeadmConfig if configured to use the KubeadmConfig bootstrapper
if machine.Spec.Bootstrap.ConfigRef != nil && machine.Spec.Bootstrap.ConfigRef.Kind == "KubeadmConfig" {
fromKubeadmConfig, err := providerIDFromKubeadmConfig(ctx, mgmtClient, packetMachine.Namespace, machine.Spec.Bootstrap.ConfigRef.Name)
if err != nil {
return "", err
}
if fromKubeadmConfig != "" {
return fromKubeadmConfig, nil
}
}

return providerIDPrefix, nil
}

// providerIDFromKubeadmConfig attempts to determine the appropriate providerID prefix to use based on the configuration
// of the referenced KubeadmConfig resource. It uses the following precedence:
// - If an explicit providerID is being configured for the kubelet through extra arguments in the InitConfiguration, use it
// - If an explicit providerID is being configured for the kubelet through extra arguments in the JoinConfiguration, use it
// (InitConfiguration and JoinConfiguration are mutually exclusive options)
// - If the PostKubeadmCommands are deploying packet-ccm, use "packet"
// - If the PostKubeadmCommands are deploying cloud-provider-equinix-metal, use "equinixmetal"
// - Otherwise, return ""
func providerIDFromKubeadmConfig(ctx context.Context, mgmtClient client.Client, namespace, name string) (string, error) {
kubeadmConfig := new(bootstrapv1.KubeadmConfig)
key := client.ObjectKey{
Name: name,
Namespace: namespace,
}

if err := mgmtClient.Get(ctx, key, kubeadmConfig); err != nil {
return "", fmt.Errorf("failed to get bootstrap resource: %w", err)
}

// providerid being set explicitly in the InitConfiguration
if kubeadmConfig.Spec.InitConfiguration != nil && kubeadmConfig.Spec.InitConfiguration.NodeRegistration.KubeletExtraArgs != nil {
if value, ok := kubeadmConfig.Spec.InitConfiguration.NodeRegistration.KubeletExtraArgs["provider-id"]; ok {
if parsed, err := noderefutil.NewProviderID(value); err == nil {
return parsed.CloudProvider(), nil
}
}
}

// providerid being set explicitly in the JoinConfiguration
if kubeadmConfig.Spec.JoinConfiguration != nil && kubeadmConfig.Spec.JoinConfiguration.NodeRegistration.KubeletExtraArgs != nil {
if value, ok := kubeadmConfig.Spec.JoinConfiguration.NodeRegistration.KubeletExtraArgs["provider-id"]; ok {
if parsed, err := noderefutil.NewProviderID(value); err == nil {
return parsed.CloudProvider(), nil
}
}
}

// inspect postkubeadmcommands
for i := range kubeadmConfig.Spec.PostKubeadmCommands {
if strings.Contains(kubeadmConfig.Spec.PostKubeadmCommands[i], "github.com/packethost/packet-ccm") {
return deprecatedProviderIDPrefix, nil
}

if strings.Contains(kubeadmConfig.Spec.PostKubeadmCommands[i], "github.com/equinix/cloud-provider-equinix-metal") {
return providerIDPrefix, nil
}
}

return "", nil
}

// providerIDFromCloudProviderDeployments attempts to introspect the workload cluster (if already available) and determine which providerID
// prefix should be used based on the deployed cloud provider. If it detects packet-ccm, then it should return "packet", if it detects
// cloud-provider-equinix-metal, then it should return "equinixmetal", otherwise it should return "".
func providerIDFromCloudProviderDeployments(ctx context.Context, mgmtClient client.Client, workloadClientGetter remote.ClusterClientGetter, cluster *clusterv1.Cluster) (string, error) {
if workloadClientGetter == nil {
workloadClientGetter = remote.NewClusterClient
}

workloadClient, err := workloadClientGetter(ctx, "capp", mgmtClient, client.ObjectKeyFromObject(cluster))
if err != nil {
// Generating the workload client can throw a URL error if the
// apiserver is not yet responding, so we need to swallow
// a timeout error.
var urlError *url.Error
switch {
case errors.As(err, &urlError):
if urlError.Timeout() {
return "", nil
}

return "", fmt.Errorf("failed to get workload cluster client: %w", err)
default:
return "", fmt.Errorf("failed to get workload cluster client: %w", err)
}
}

err = hasWorkloadDeployment(ctx, workloadClient, metav1.NamespaceSystem, "cloud-provider-equinix-metal")
switch {
case err == nil:
// CPEM is deployed, use equinixmetal
return providerIDPrefix, nil
case err != nil:
// This is needed because apierrors doesn't handle wrapped errors
// in the v0.17.17, can use client.IgnoreNotFound with later versions
// of kubernetes dependencies.
var apiError *apierrors.StatusError
if errors.As(err, &apiError) {
if !apierrors.IsNotFound(apiError) {
return "", err
}
} else {
return "", err
}
}

err = hasWorkloadDeployment(ctx, workloadClient, metav1.NamespaceSystem, "packet-cloud-controller-manager")
switch {
case err == nil:
// packet-ccm is deployed, use packet
return deprecatedProviderIDPrefix, nil
case err != nil:
// This is needed because apierrors doesn't handle wrapped errors
// in the v0.17.17, can use client.IgnoreNotFound with later versions
// of kubernetes dependencies.
var apiError *apierrors.StatusError
if errors.As(err, &apiError) {
if !apierrors.IsNotFound(apiError) {
return "", err
}
} else {
return "", err
}
}

return "", nil
}

func hasWorkloadDeployment(ctx context.Context, workloadClient client.Client, namespace, name string) error {
deployment := new(appsv1.Deployment)
key := client.ObjectKey{
Namespace: namespace,
Name: name,
}

if err := workloadClient.Get(ctx, key, deployment); err != nil {
return fmt.Errorf("failed to query workload cluster for %s: %w", key.String(), err)
}

return nil
}

func providerIDPrefixFromPacketMachine(packetMachine *infrav1.PacketMachine) string {
preexistingProviderID := ptr.Deref(packetMachine.Spec.ProviderID, "")
if preexistingProviderID != "" {
if parsed, err := noderefutil.NewProviderID(preexistingProviderID); err == nil {
return parsed.CloudProvider()
}
}

return ""
}

// PatchObject persists the machine spec and status.
func (m *MachineScope) PatchObject(ctx context.Context) error {
// Always update the readyCondition by summarizing the state of other conditions.
Expand Down
Loading

0 comments on commit 7d01003

Please sign in to comment.