Skip to content

Commit

Permalink
Merge pull request #3 from edenlabllc/feature/FFS-1-implement-aws-iam…
Browse files Browse the repository at this point in the history
…-provisioneroperatorsinfra-for-provisioning-iam-resources-for-aws-cluster-api

Implement basic reconciliation logic in controller and manager.
  • Loading branch information
anovikov-el authored Dec 12, 2024
2 parents d57aa3b + 64bb61f commit 05313cf
Show file tree
Hide file tree
Showing 11 changed files with 721 additions and 280 deletions.
18 changes: 13 additions & 5 deletions api/v1alpha1/awsiamprovision_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,37 @@ limitations under the License.
package v1alpha1

import (
iamctrlv1alpha1 "github.com/aws-controllers-k8s/iam-controller/apis/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.

type AWSIAMProvisionRole struct {
Spec iamctrlv1alpha1.RoleSpec `json:"spec"`
}

// AWSIAMProvisionSpec defines the desired state of AWSIAMProvision.
type AWSIAMProvisionSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file

// Foo is an example field of AWSIAMProvision. Edit awsiamprovision_types.go to remove/update
Foo string `json:"foo,omitempty"`
EksClusterName string `json:"eksClusterName"`
Roles map[string]AWSIAMProvisionRole `json:"roles"`
}

// AWSIAMProvisionStatus defines the observed state of AWSIAMProvision.
type AWSIAMProvisionStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file

Message string `json:"message,omitempty"`
LastUpdatedTime *metav1.Time `json:"lastUpdatedTime,omitempty"`
Phase string `json:"phase,omitempty"`
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="PHASE",type=string,JSONPath=`.status.phase`
// +kubebuilder:printcolumn:name="LAST-UPDATED-TIME",type=string,JSONPath=".status.lastUpdatedTime"

// AWSIAMProvision is the Schema for the awsiamprovisions API.
type AWSIAMProvision struct {
Expand Down
31 changes: 29 additions & 2 deletions api/v1alpha1/zz_generated.deepcopy.go

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

116 changes: 58 additions & 58 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,25 @@ limitations under the License.
package main

import (
"crypto/tls"
"flag"
"fmt"
"os"
"strings"

// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
// to ensure that exec-entrypoint and run can make use of them.
_ "k8s.io/client-go/plugin/pkg/client/auth"

iamctrlv1alpha1 "github.com/aws-controllers-k8s/iam-controller/apis/v1alpha1"
"go.uber.org/zap/zapcore"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/controller-runtime/pkg/cache"
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
// to ensure that exec-entrypoint and run can make use of them.
_ "k8s.io/client-go/plugin/pkg/client/auth"
cpv1beta2 "sigs.k8s.io/cluster-api-provider-aws/v2/controlplane/eks/api/v1beta2"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
"sigs.k8s.io/controller-runtime/pkg/webhook"

iamv1alpha1 "aws-iam-provisioner.operators.infra/api/v1alpha1"
"aws-iam-provisioner.operators.infra/internal/controller"
Expand All @@ -47,81 +49,39 @@ var (

func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))

utilruntime.Must(iamv1alpha1.AddToScheme(scheme))
utilruntime.Must(iamctrlv1alpha1.AddToScheme(scheme))
utilruntime.Must(cpv1beta2.AddToScheme(scheme))
// +kubebuilder:scaffold:scheme
}

func main() {
var metricsAddr string
var enableLeaderElection bool
var probeAddr string
var secureMetrics bool
var enableHTTP2 bool
var tlsOpts []func(*tls.Config)
flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+
"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
"Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")
flag.BoolVar(&secureMetrics, "metrics-secure", true,
"If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.")
flag.BoolVar(&enableHTTP2, "enable-http2", false,
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
opts := zap.Options{
Development: true,
}
opts := zap.Options{Development: true, StacktraceLevel: zapcore.DPanicLevel}
opts.BindFlags(flag.CommandLine)
flag.Parse()

ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))

// if the enable-http2 flag is false (the default), http/2 should be disabled
// due to its vulnerabilities. More specifically, disabling http/2 will
// prevent from being vulnerable to the HTTP/2 Stream Cancellation and
// Rapid Reset CVEs. For more information see:
// - https://github.com/advisories/GHSA-qppj-fm5r-hxr3
// - https://github.com/advisories/GHSA-4374-p667-p6c8
disableHTTP2 := func(c *tls.Config) {
setupLog.Info("disabling http/2")
c.NextProtos = []string{"http/1.1"}
}

if !enableHTTP2 {
tlsOpts = append(tlsOpts, disableHTTP2)
}

webhookServer := webhook.NewServer(webhook.Options{
TLSOpts: tlsOpts,
})

// Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server.
// More info:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19.1/pkg/metrics/server
// - https://book.kubebuilder.io/reference/metrics.html
metricsServerOptions := metricsserver.Options{
BindAddress: metricsAddr,
SecureServing: secureMetrics,
TLSOpts: tlsOpts,
BindAddress: metricsAddr,
}

if secureMetrics {
// FilterProvider is used to protect the metrics endpoint with authn/authz.
// These configurations ensure that only authorized users and service accounts
// can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info:
// https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19.1/pkg/metrics/filters#WithAuthenticationAndAuthorization
metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization

// TODO(user): If CertDir, CertName, and KeyName are not specified, controller-runtime will automatically
// generate self-signed certificates for the metrics server. While convenient for development and testing,
// this setup is not recommended for production.
}

mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
options := ctrl.Options{
Scheme: scheme,
Metrics: metricsServerOptions,
WebhookServer: webhookServer,
HealthProbeBindAddress: probeAddr,
LeaderElection: enableLeaderElection,
LeaderElectionID: "223fc060.aws.edenlab.io",
Expand All @@ -136,15 +96,40 @@ func main() {
// if you are doing or is intended to do any operation such as perform cleanups
// after the manager stops then its usage might be unsafe.
// LeaderElectionReleaseOnCancel: true,
})
}

watchNamespaces, err := getWatchNamespaces()
if err != nil {
setupLog.Info("unable to get WATCH_NAMESPACES env, " +
"the manager will watch and manage resources in all namespaces")
}

// Add support for watching multiple namespaces set in WATCH_NAMESPACES (e.g. ns1,ns2)
if len(watchNamespaces) > 0 {
setupLog.Info("manager set up with multiple namespaces", "namespaces", watchNamespaces)

cacheConfigMap := map[string]cache.Config{}

for _, namespace := range strings.Split(watchNamespaces, ",") {
cacheConfigMap[namespace] = cache.Config{}
}

options.Cache = cache.Options{
DefaultNamespaces: cacheConfigMap,
}
}

mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), options)

if err != nil {
setupLog.Error(err, "unable to start manager")
os.Exit(1)
}

if err = (&controller.AWSIAMProvisionReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Client: mgr.GetClient(),
ReconciliationManager: &controller.ReconciliationManager{},
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "AWSIAMProvision")
os.Exit(1)
Expand All @@ -166,3 +151,18 @@ func main() {
os.Exit(1)
}
}

// getWatchNamespaces returns the Namespace the operator should be watching for changes
func getWatchNamespaces() (string, error) {
// WatchNamespaceEnvVar is the constant for env variable WATCH_NAMESPACE
// which specifies the Namespace to watch.
// An empty value means the operator is running with cluster scope.
var watchNamespaceEnvVar = "WATCH_NAMESPACES"

ns, found := os.LookupEnv(watchNamespaceEnvVar)
if !found {
return "", fmt.Errorf("%s env must be set", watchNamespaceEnvVar)
}

return ns, nil
}
Loading

0 comments on commit 05313cf

Please sign in to comment.