Skip to content
This repository has been archived by the owner on Apr 11, 2024. It is now read-only.

Commit

Permalink
feat: adds a validation hook
Browse files Browse the repository at this point in the history
  • Loading branch information
faiq committed Apr 9, 2024
1 parent 3f9425f commit d6a5fa8
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 0 deletions.
29 changes: 29 additions & 0 deletions api/variables/variables.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package variables

import (
"encoding/json"
"fmt"

runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
)

func UnmarshalRuntimeVariable[T any](runtimeVariable *runtimehooksv1.Variable, obj *T) error {
err := json.Unmarshal(runtimeVariable.Value.Raw, obj)
if err != nil {
return fmt.Errorf("error unmarshalling variable: %w", err)
}

return nil
}

func GetRuntimhookVariableByName(
name string,
variables []runtimehooksv1.Variable,
) (*runtimehooksv1.Variable, int) {
for i, runtimevar := range variables {
if runtimevar.Name == name {
return &runtimevar, i
}
}
return nil, -1
}
3 changes: 3 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
dockermutation "github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/docker/mutation"
dockerworkerconfig "github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/docker/workerconfig"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/lifecycle"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/validation"
nutanixclusterconfig "github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/nutanix/clusterconfig"
nutanixmutation "github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/nutanix/mutation"
nutanixworkerconfig "github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/nutanix/workerconfig"
Expand Down Expand Up @@ -84,6 +85,7 @@ func main() {

genericLifecycleHandlers := lifecycle.New(globalOptions)

validationHandlers := validation.New()
// Initialize and parse command line flags.
logs.AddFlags(pflag.CommandLine, logs.SkipLoggingConfigurationFlags())
logsv1.AddFlags(logOptions, pflag.CommandLine)
Expand Down Expand Up @@ -142,6 +144,7 @@ func main() {
}

var allHandlers []handlers.Named
allHandlers = append(allHandlers, validationHandlers.AllHandlers(mgr)...)
allHandlers = append(allHandlers, genericLifecycleHandlers.AllHandlers(mgr)...)
allHandlers = append(allHandlers, awsMetaHandlers...)
allHandlers = append(allHandlers, dockerMetaHandlers...)
Expand Down
20 changes: 20 additions & 0 deletions pkg/handlers/generic/validation/handlers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package validation

import (
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/handlers"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/validation/helm"
"sigs.k8s.io/controller-runtime/pkg/manager"
)

type Handlers struct{}

func New() *Handlers {
return &Handlers{}
}

func (h *Handlers) AllHandlers(mgr manager.Manager) []handlers.Named {
validationHandler := helm.New(mgr.GetClient())
return []handlers.Named{
validationHandler,
}
}
78 changes: 78 additions & 0 deletions pkg/handlers/generic/validation/helm/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package helm

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

"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/api/v1alpha1"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/api/variables"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/clusterconfig"
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
ctrl "sigs.k8s.io/controller-runtime"
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
)

type HelmRegistryValidator struct {
client ctrlclient.Client
variableName string
}

func New(
c ctrlclient.Client,
) *HelmRegistryValidator {
return &HelmRegistryValidator{
client: c,
variableName: clusterconfig.MetaVariableName,
}
}

func (h *HelmRegistryValidator) Name() string {
return "HelmRegistryValidator"
}

func (h *HelmRegistryValidator) ValidateTopology(
ctx context.Context,
req *runtimehooksv1.ValidateTopologyRequest,
res *runtimehooksv1.ValidateTopologyResponse,
) {
log := ctrl.LoggerFrom(ctx)
clusterVar, ind := variables.GetRuntimhookVariableByName(h.variableName, req.Variables)
if ind == -1 {
log.V(5).Info(fmt.Sprintf("did not find variable %s in %v", h.variableName, req.Variables))
return
}
var cluster v1alpha1.ClusterConfig
if err := variables.UnmarshalRuntimeVariable[v1alpha1.ClusterConfig](clusterVar, &cluster); err != nil {
failString := fmt.Sprintf("failed to unmarshal variable %v to clusterConfig", clusterVar)
log.Error(err, failString)
res.SetStatus(runtimehooksv1.ResponseStatusFailure)
res.SetMessage(failString)
return
}
helmChartRepo := cluster.Spec.Addons.HelmChartRepository
cl := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
}
resp, err := cl.Get(fmt.Sprintf("%s/v2", *helmChartRepo))
if err != nil {
failString := fmt.Sprintf("failed to ping provided helm registry %s", *helmChartRepo)
log.Error(err, failString)
res.SetStatus(runtimehooksv1.ResponseStatusFailure)
res.SetMessage(failString)
return
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusUnauthorized {
res.SetStatus(runtimehooksv1.ResponseStatusSuccess)
return
}
failString := fmt.Sprintf("failed to get 401 or 200 response from hitting registry: %s got status: %d", *helmChartRepo, resp.StatusCode)
log.Error(err, failString)
res.SetStatus(runtimehooksv1.ResponseStatusFailure)
res.SetMessage(failString)
return
}

0 comments on commit d6a5fa8

Please sign in to comment.