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

fix: move awsacfg resource creation from Helm chart to controller #61

Merged
merged 18 commits into from
Mar 16, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
9 changes: 9 additions & 0 deletions charts/kyverno-aws-adapter/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ spec:
image: {{ include "kyverno-aws-adapter.image" . }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
name: manager
env:
- name: ADAPTER_NAME
value: {{ include "kyverno-aws-adapter.fullname" . }}
- name: ADAPTER_NAMESPACE
value: {{ .Release.Namespace }}
- name: CLUSTER_NAME
value: {{ required "EKS cluster name is required" .Values.eksCluster.name }}
- name: CLUSTER_REGION
value: {{ required "EKS cluster region is required" .Values.eksCluster.region }}
{{- if .Values.pollInterval }}
args:
- --sync-period={{ .Values.pollInterval }}
Expand Down
9 changes: 0 additions & 9 deletions charts/kyverno-aws-adapter/templates/resource.yaml

This file was deleted.

35 changes: 31 additions & 4 deletions controllers/awsadapterconfig_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ import (

"github.com/go-logr/logr"
"github.com/google/go-cmp/cmp"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
apimachineryTypes "k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
Expand Down Expand Up @@ -86,13 +88,13 @@ func (r *AWSAdapterConfigReconciler) Reconcile(ctx context.Context, req ctrl.Req
}
l.Info("Reconciling", "req", req)

l.Info("Loading AWS SDK config")
l.Info("Loading AWS Adapter config")
cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(*objOld.Spec.Region))
if err != nil {
l.Error(err, "error occurred while loading aws sdk config")
return r.updateLastPollStatusFailure(ctx, objOld, "error occurred while loading aws sdk config", err, &l, time.Now())
l.Error(err, "error occurred while loading aws adapter config")
return r.updateLastPollStatusFailure(ctx, objOld, "error occurred while loading aws adapter config", err, &l, time.Now())
}
l.Info("AWS SDK config loaded successfully")
l.Info("AWS Adapter config loaded successfully")

stsClient := sts.NewFromConfig(cfg)
ec2Client := ec2.NewFromConfig(cfg)
Expand Down Expand Up @@ -444,6 +446,31 @@ func (r *AWSAdapterConfigReconciler) updateLastPollStatusFailure(ctx context.Con
return ctrl.Result{RequeueAfter: r.RequeueInterval}, nil
}

func (r *AWSAdapterConfigReconciler) IsAWSAdapterConfigPresent(adapterName, adapterNamespace string) (bool, error) {
obj := &securityv1alpha1.AWSAdapterConfig{}
err := r.Get(context.TODO(), apimachineryTypes.NamespacedName{Namespace: adapterNamespace, Name: adapterName}, obj)
if err == nil {
return true, nil
}
if errors.IsNotFound(err) {
return false, nil
}
return false, err
}

func (r *AWSAdapterConfigReconciler) CreateAWSAdapterConfig(clusterName, clusterRegion, adapterName, adapterNamespace string) error {
return r.Create(context.TODO(), &securityv1alpha1.AWSAdapterConfig{
Copy link
Contributor

@pns-nirmata pns-nirmata Mar 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If any of the above are empty, then don't create instead of failing and exiting.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I moved the required parameters and their error handling to the main file, so that we can right away return if all required params are not present.

ObjectMeta: metav1.ObjectMeta{
Name: adapterName,
Namespace: adapterNamespace,
},
Spec: securityv1alpha1.AWSAdapterConfigSpec{
Name: &clusterName,
Region: &clusterRegion,
},
})
}

func isStatusVacuous(status *securityv1alpha1.AWSAdapterConfigStatus) bool {
return (status.LastUpdatedTimestamp == nil &&
status.LastPollInfo == securityv1alpha1.LastPollInfo{} &&
Expand Down
24 changes: 24 additions & 0 deletions docs/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,27 @@ kubectl get awsacfg -n nirmata-aws-adapter
NAME ... CLUSTER NAME ... LAST POLLED STATUS
kyverno-aws-adapter ... cluster-name ... success
```

### Uninstalling the AWS Adapter Helm chart

To uninstall the AWS Adapter Helm chart, use the following command.

```bash
helm uninstall kyverno-aws-adapter --namespace nirmata-aws-adapter
```

This removes all the Kubernetes components associated with the chart and deletes the release.

The `awsadapterconfigs.security.nirmata.io` CRD created by this chart is not removed by default and should be manually cleaned up. So, after uninstalling helm chart the following command can be used to remove the CRD.

```bash
kubectl delete crd awsadapterconfigs.security.nirmata.io
```

### Deleting the AWSAdapterConfig

The `AWSAdapterConfig` CR is not deleted by `helm uninstall` or by deleting the pod, and must be manually cleaned up.

```bash
kubectl delete awsacfg kyverno-aws-adapter -n nirmata-aws-adapter
```
81 changes: 78 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"

Expand Down Expand Up @@ -92,11 +93,12 @@ func main() {
os.Exit(1)
}

if err = (&controllers.AWSAdapterConfigReconciler{
Client: mgr.GetClient(),
r := &controllers.AWSAdapterConfigReconciler{
Client: getClient(),
Scheme: mgr.GetScheme(),
RequeueInterval: time.Duration(syncPeriod) * time.Minute,
}).SetupWithManager(mgr); err != nil {
}
if err = r.SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "AWSAdapterConfig")
os.Exit(1)
}
Expand All @@ -111,9 +113,82 @@ func main() {
os.Exit(1)
}

createAWSAdapterConfigIfNotPresent(r)

pns-nirmata marked this conversation as resolved.
Show resolved Hide resolved
setupLog.Info("starting manager")
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
setupLog.Error(err, "problem running manager")
os.Exit(1)
}
}

func getClient() client.Client {
cl, err := client.New(ctrl.GetConfigOrDie(), client.Options{Scheme: scheme})
if err != nil {
setupLog.Error(err, "unable to create client")
os.Exit(1)
}
return cl
}

type requiredParams struct {
clusterName string
clusterRegion string
adapterName string
adapterNamespace string
}

func (rp *requiredParams) areAllPresent() bool {
return rp.clusterName != "" && rp.clusterRegion != "" && rp.adapterName != "" && rp.adapterNamespace != ""
}

func createAWSAdapterConfigIfNotPresent(r *controllers.AWSAdapterConfigReconciler) {
rp := requiredParams{
clusterName: getClusterName(),
clusterRegion: getClusterRegion(),
adapterName: getAdapterName(),
adapterNamespace: getAdapterNamespace(),
}

if rp.areAllPresent() {
setupLog.Info("One or more of the required parameters could not be found: clusterName='%s' clusterRegion='%s' adapterName='%s' adapterNamespace='%s'", rp.clusterName, rp.clusterRegion, rp.adapterName, rp.adapterNamespace)
return
}

if isAWSAdapterConfigPresent, err := r.IsAWSAdapterConfigPresent(rp.adapterName, rp.adapterNamespace); err != nil {
setupLog.Error(err, "problem checking if AWS Adapter config exists")
os.Exit(1)
} else if isAWSAdapterConfigPresent {
setupLog.Info("AWS Adapter config already exists. Skipping resource creation.")
} else {
setupLog.Info("creating AWS Adapter config")
if err := r.CreateAWSAdapterConfig(rp.clusterName, rp.clusterRegion, rp.adapterName, rp.adapterNamespace); err != nil {
setupLog.Error(err, "unable to create AWS Adapter config")
os.Exit(1)
}
setupLog.Info("AWS Adapter config created successfully")
}
}

const (
ADAPTER_NAME_ENV_VAR = "ADAPTER_NAME"
ADAPTER_NAMESPACE_ENV_VAR = "ADAPTER_NAMESPACE"
CLUSTER_NAME_ENV_VAR = "CLUSTER_NAME"
CLUSTER_REGION_ENV_VAR = "CLUSTER_REGION"
)

func getAdapterName() string {
return os.Getenv(ADAPTER_NAME_ENV_VAR)
}

func getAdapterNamespace() string {
return os.Getenv(ADAPTER_NAMESPACE_ENV_VAR)
}

func getClusterName() string {
return os.Getenv(CLUSTER_NAME_ENV_VAR)
}

func getClusterRegion() string {
return os.Getenv(CLUSTER_REGION_ENV_VAR)
}