Skip to content

Commit

Permalink
Make proxmoxcluster.Spec.CredentialsRef used whenever it's specified
Browse files Browse the repository at this point in the history
  • Loading branch information
mcbenjemaa committed May 23, 2024
1 parent 15bb25a commit 2dd056b
Show file tree
Hide file tree
Showing 6 changed files with 225 additions and 27 deletions.
39 changes: 39 additions & 0 deletions api/v1alpha1/proxmoxcluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/errors"
"sigs.k8s.io/controller-runtime/pkg/client"
)

Expand Down Expand Up @@ -146,6 +147,44 @@ type ProxmoxClusterStatus struct {
// +optional
NodeLocations *NodeLocations `json:"nodeLocations,omitempty"`

// FailureReason will be set in the event that there is a terminal problem
// reconciling the Machine and will contain a succinct value suitable
// for machine interpretation.
//
// This field should not be set for transitive errors that a controller
// faces that are expected to be fixed automatically over
// time (like service outages), but instead indicate that something is
// fundamentally wrong with the Machine's spec or the configuration of
// the controller, and that manual intervention is required. Examples
// of terminal errors would be invalid combinations of settings in the
// spec, values that are unsupported by the controller, or the
// responsible controller itself being critically misconfigured.
//
// Any transient errors that occur during the reconciliation of ProxmoxCluster
// can be added as events to the ProxmoxCluster object and/or logged in the
// controller's output.
// +optional
FailureReason *errors.ClusterStatusError `json:"failureReason,omitempty"`

// FailureMessage will be set in the event that there is a terminal problem
// reconciling the Machine and will contain a more verbose string suitable
// for logging and human consumption.
//
// This field should not be set for transitive errors that a controller
// faces that are expected to be fixed automatically over
// time (like service outages), but instead indicate that something is
// fundamentally wrong with the Machine's spec or the configuration of
// the controller, and that manual intervention is required. Examples
// of terminal errors would be invalid combinations of settings in the
// spec, values that are unsupported by the controller, or the
// responsible controller itself being critically misconfigured.
//
// Any transient errors that occur during the reconciliation of ProxmoxMachines
// can be added as events to the ProxmoxCluster object and/or logged in the
// controller's output.
// +optional
FailureMessage *string `json:"failureMessage,omitempty"`

// Conditions defines current service state of the ProxmoxCluster.
// +optional
Conditions clusterv1.Conditions `json:"conditions,omitempty"`
Expand Down
15 changes: 15 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

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

25 changes: 4 additions & 21 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (

"github.com/go-logr/logr"
"github.com/luthermonson/go-proxmox"
"github.com/pkg/errors"
"github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
Expand Down Expand Up @@ -185,8 +184,11 @@ func setupReconcilers(ctx context.Context, mgr ctrl.Manager, client capmox.Clien
}

func setupProxmoxClient(ctx context.Context, logger logr.Logger) (capmox.Client, error) {
// TODO, check if we need to delete tls config
// You can disable security check for a client:
if ProxmoxURL == "" || ProxmoxTokenID == "" || ProxmoxSecret == "" {
return nil, nil
}
// TODO, check if we need to delete tls config
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, //nolint:gosec
}
Expand Down Expand Up @@ -214,23 +216,4 @@ func initFlagsAndEnv(fs *pflag.FlagSet) {
"If true, run webhook server alongside manager")

feature.MutableGates.AddFlag(fs)

err := validate()
if err != nil {
setupLog.Error(err, "validate fails")
os.Exit(1)
}
}

func validate() error {
if ProxmoxURL == "" {
return errors.New("required variable `PROXMOX_URL` is not set")
}
if ProxmoxTokenID == "" {
return errors.New("required variable `PROXMOX_TOKEN` is not set")
}
if ProxmoxSecret == "" {
return errors.New("required variable `PROXMOX_SECRET` is not set")
}
return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,45 @@ spec:
- host
- port
type: object
credentialsRef:
description: CredentialsRef is a reference to a Secret that contains
the credentials to use for provisioning this cluster. If not supplied
then the credentials of the controller will be used.
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead of
an entire object, this string should contain a valid JSON/Go
field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container within
a pod, this would take on a value like: "spec.containers{name}"
(where "name" refers to the name of the container that triggered
the event) or if no container name is specified "spec.containers[2]"
(container with index 2 in this pod). This syntax is chosen
only to have some well-defined way of referencing a part of
an object. TODO: this design is not final and this field is
subject to change in the future.'
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which this reference
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
x-kubernetes-map-type: atomic
dnsServers:
description: DNSServers contains information about nameservers used
by the machines.
Expand Down Expand Up @@ -690,6 +729,37 @@ spec:
- type
type: object
type: array
failureMessage:
description: "FailureMessage will be set in the event that there is
a terminal problem reconciling the Machine and will contain a more
verbose string suitable for logging and human consumption. \n This
field should not be set for transitive errors that a controller
faces that are expected to be fixed automatically over time (like
service outages), but instead indicate that something is fundamentally
wrong with the Machine's spec or the configuration of the controller,
and that manual intervention is required. Examples of terminal errors
would be invalid combinations of settings in the spec, values that
are unsupported by the controller, or the responsible controller
itself being critically misconfigured. \n Any transient errors that
occur during the reconciliation of ProxmoxMachines can be added
as events to the ProxmoxCluster object and/or logged in the controller's
output."
type: string
failureReason:
description: "FailureReason will be set in the event that there is
a terminal problem reconciling the Machine and will contain a succinct
value suitable for machine interpretation. \n This field should
not be set for transitive errors that a controller faces that are
expected to be fixed automatically over time (like service outages),
but instead indicate that something is fundamentally wrong with
the Machine's spec or the configuration of the controller, and that
manual intervention is required. Examples of terminal errors would
be invalid combinations of settings in the spec, values that are
unsupported by the controller, or the responsible controller itself
being critically misconfigured. \n Any transient errors that occur
during the reconciliation of ProxmoxCluster can be added as events
to the ProxmoxCluster object and/or logged in the controller's output."
type: string
inClusterIpPoolRef:
description: InClusterIPPoolRef is the reference to the created in-cluster
IP pool.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,47 @@ spec:
- host
- port
type: object
credentialsRef:
description: CredentialsRef is a reference to a Secret that
contains the credentials to use for provisioning this cluster.
If not supplied then the credentials of the controller will
be used.
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead
of an entire object, this string should contain a valid
JSON/Go field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container
within a pod, this would take on a value like: "spec.containers{name}"
(where "name" refers to the name of the container that
triggered the event) or if no container name is specified
"spec.containers[2]" (container with index 2 in this
pod). This syntax is chosen only to have some well-defined
way of referencing a part of an object. TODO: this design
is not final and this field is subject to change in
the future.'
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which this reference
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
x-kubernetes-map-type: atomic
dnsServers:
description: DNSServers contains information about nameservers
used by the machines.
Expand Down
62 changes: 56 additions & 6 deletions pkg/scope/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,25 @@ package scope

import (
"context"
"crypto/tls"
"net/http"

"github.com/go-logr/logr"
"github.com/luthermonson/go-proxmox"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
"k8s.io/utils/ptr"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
clustererrors "sigs.k8s.io/cluster-api/errors"
"sigs.k8s.io/cluster-api/util/conditions"
"sigs.k8s.io/cluster-api/util/patch"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"

infrav1alpha1 "github.com/ionos-cloud/cluster-api-provider-proxmox/api/v1alpha1"
"github.com/ionos-cloud/cluster-api-provider-proxmox/pkg/kubernetes/ipam"
"github.com/ionos-cloud/cluster-api-provider-proxmox/pkg/proxmox"
capmox "github.com/ionos-cloud/cluster-api-provider-proxmox/pkg/proxmox"
"github.com/ionos-cloud/cluster-api-provider-proxmox/pkg/proxmox/goproxmox"
)

// ClusterScopeParams defines the input parameters used to create a new Scope.
Expand All @@ -39,7 +46,7 @@ type ClusterScopeParams struct {
Logger *logr.Logger
Cluster *clusterv1.Cluster
ProxmoxCluster *infrav1alpha1.ProxmoxCluster
ProxmoxClient proxmox.Client
ProxmoxClient capmox.Client
ControllerName string
IPAMHelper *ipam.Helper
}
Expand All @@ -53,7 +60,7 @@ type ClusterScope struct {
Cluster *clusterv1.Cluster
ProxmoxCluster *infrav1alpha1.ProxmoxCluster

ProxmoxClient proxmox.Client
ProxmoxClient capmox.Client
controllerName string

IPAMHelper *ipam.Helper
Expand All @@ -74,9 +81,6 @@ func NewClusterScope(params ClusterScopeParams) (*ClusterScope, error) {
if params.IPAMHelper == nil {
return nil, errors.New("IPAMHelper is required when creating a ClusterScope")
}
if params.ProxmoxClient == nil {
return nil, errors.New("ProxmoxClient is required when creating a ClusterScope")
}
if params.Logger == nil {
logger := log.FromContext(context.Background())
params.Logger = &logger
Expand All @@ -99,9 +103,55 @@ func NewClusterScope(params ClusterScopeParams) (*ClusterScope, error) {

clusterScope.patchHelper = helper

if clusterScope.ProxmoxClient == nil && clusterScope.ProxmoxCluster.Spec.CredentialsRef == nil {
// Fail the cluster if no credentials found.
// set failure reason
clusterScope.ProxmoxCluster.Status.FailureMessage = ptr.To("No credentials found, ProxmoxCluster missing credentialsRef")
clusterScope.ProxmoxCluster.Status.FailureReason = ptr.To(clustererrors.InvalidConfigurationClusterError)

if err = clusterScope.Close(); err != nil {
return nil, err
}
return nil, errors.New("No credentials found, ProxmoxCluster missing credentialsRef")
} else if clusterScope.ProxmoxCluster.Spec.CredentialsRef != nil {
// using proxmoxcluster.spec.credentialsRef
pmoxClient, err := clusterScope.setupProxmoxClient(context.TODO())
if err != nil {
return nil, errors.Wrap(err, "Unable to initialize ProxmoxClient")
}
clusterScope.ProxmoxClient = pmoxClient
}

return clusterScope, nil
}

func (s *ClusterScope) setupProxmoxClient(ctx context.Context) (capmox.Client, error) {
// get the credentials secret
secret := corev1.Secret{}
err := s.client.Get(ctx, client.ObjectKey{
Namespace: s.ProxmoxCluster.Spec.CredentialsRef.Namespace,
Name: s.ProxmoxCluster.Spec.CredentialsRef.Name,
}, &secret)
if err != nil {
return nil, errors.Wrap(err, "failed to get credentials secret")
}

token := string(secret.Data["token"])
tokenSecret := string(secret.Data["secret"])
url := string(secret.Data["url"])

// TODO, check if we need to delete tls config
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, //nolint:gosec
}

httpClient := &http.Client{Transport: tr}
return goproxmox.NewAPIClient(ctx, *s.Logger, url,
proxmox.WithHTTPClient(httpClient),
proxmox.WithAPIToken(token, tokenSecret),
)
}

// Name returns the CAPI cluster name.
func (s *ClusterScope) Name() string {
return s.Cluster.Name
Expand Down

0 comments on commit 2dd056b

Please sign in to comment.