Skip to content

Commit

Permalink
Merge pull request #17 from adyanth/goreport-enhancement
Browse files Browse the repository at this point in the history
Go Report Card enhancement
  • Loading branch information
adyanth authored Jan 29, 2022
2 parents d8543be + 10653ca commit 2b176c6
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 64 deletions.
6 changes: 3 additions & 3 deletions api/v1alpha1/tunnel_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
// 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.

// Existing Tunnel spec. Needs either a Tunnel Id or a Name to find it on Cloudflare.
// ExistingTunnel spec needs either a Tunnel Id or a Name to find it on Cloudflare.
type ExistingTunnel struct {
//+kubebuilder:validation:Optional
// Existing Tunnel ID to run on. Tunnel ID and Tunnel Name cannot be both empty. If both are provided, ID is used if valid, else falls back to Name.
Expand All @@ -34,14 +34,14 @@ type ExistingTunnel struct {
Name string `json:"name,omitempty"`
}

// New Tunnel spec. Needs a name to create a Tunnel on Cloudflare.
// NewTunnel spec needs a name to create a Tunnel on Cloudflare.
type NewTunnel struct {
//+kubebuilder:validation:Required
// Tunnel name to create on Cloudflare.
Name string `json:"name,omitempty"`
}

// Cloudflare Details spec. All the necessary parameters needed to connect to the Cloudflare API.
// CloudflareDetails spec contains all the necessary parameters needed to connect to the Cloudflare API.
type CloudflareDetails struct {
//+kubebuilder:validation:Required
// Cloudflare Domain to which this tunnel belongs to
Expand Down
25 changes: 13 additions & 12 deletions controllers/cloudflare_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/go-logr/logr"
)

// Cloudflare API base URL from https://api.cloudflare.com/#getting-started-endpoints.
// CLOUDFLARE_ENDPOINT is the Cloudflare API base URL from https://api.cloudflare.com/#getting-started-endpoints.
const CLOUDFLARE_ENDPOINT = "https://api.cloudflare.com/client/v4/"

// CloudflareAPI config object holding all relevant fields to use the API
Expand All @@ -32,7 +32,7 @@ type CloudflareAPI struct {
ValidZoneId string
}

// Cloudflare API Response object containing a slice of Results with a Name and Id field
// CloudflareAPIResponse object containing Result with a Name and Id field (includes an optional CredentialsFile for Tunnel responses)
type CloudflareAPIResponse struct {
Result struct {
Id string
Expand All @@ -45,6 +45,7 @@ type CloudflareAPIResponse struct {
}
}

// CloudflareAPIMultiResponse object containing a slice of Results with a Name and Id field
type CloudflareAPIMultiResponse struct {
Result []struct {
Id string
Expand All @@ -56,7 +57,7 @@ type CloudflareAPIMultiResponse struct {
Success bool
}

// Cloudflare API Input for creating a Tunnel
// CloudflareAPITunnelCreate object containing Cloudflare API Input for creating a Tunnel
type CloudflareAPITunnelCreate struct {
Name string
TunnelSecret string `json:"tunnel_secret"`
Expand All @@ -78,7 +79,7 @@ func (c CloudflareAPI) addAuthHeader(req *http.Request, delete bool) error {
return nil
}

// Create a Cloudflare Tunnel and return the tunnel Id and credentials file
// CreateCloudflareTunnel creates a Cloudflare Tunnel and returns the tunnel Id and credentials file
func (c *CloudflareAPI) CreateCloudflareTunnel() (string, string, error) {
if _, err := c.GetAccountId(); err != nil {
c.Log.Error(err, "error code in getting account ID")
Expand Down Expand Up @@ -134,7 +135,7 @@ func (c *CloudflareAPI) CreateCloudflareTunnel() (string, string, error) {
return tunnelResponse.Result.Id, string(creds), nil
}

// Delete a Cloudflare Tunnel
// DeleteCloudflareTunnel deletes a Cloudflare Tunnel
func (c *CloudflareAPI) DeleteCloudflareTunnel() error {
if err := c.ValidateAll(); err != nil {
c.Log.Error(err, "Error in validation")
Expand Down Expand Up @@ -168,7 +169,7 @@ func (c *CloudflareAPI) DeleteCloudflareTunnel() error {
return nil
}

// Validate the contents of the CloudflareAPI struct
// ValidateAll validates the contents of the CloudflareAPI struct
func (c *CloudflareAPI) ValidateAll() error {
c.Log.Info("In validation")
if _, err := c.GetAccountId(); err != nil {
Expand All @@ -187,7 +188,7 @@ func (c *CloudflareAPI) ValidateAll() error {
return nil
}

// Get the AccountId from Account Name
// GetAccountId gets AccountId from Account Name
func (c *CloudflareAPI) GetAccountId() (string, error) {
if c.ValidAccountId != "" {
return c.ValidAccountId, nil
Expand Down Expand Up @@ -273,7 +274,7 @@ func (c *CloudflareAPI) getAccountIdByName() (string, error) {
}
}

// Get Tunnel Id from available information
// GetTunnelId gets Tunnel Id from available information
func (c *CloudflareAPI) GetTunnelId() (string, error) {
if c.ValidTunnelId != "" {
return c.ValidTunnelId, nil
Expand Down Expand Up @@ -376,7 +377,7 @@ func (c *CloudflareAPI) getTunnelIdByName() (string, error) {
}
}

// Get Tunnel Credentials from Tunnel secret
// GetTunnelCreds gets Tunnel Credentials from Tunnel secret
func (c *CloudflareAPI) GetTunnelCreds(tunnelSecret string) (string, error) {
if _, err := c.GetAccountId(); err != nil {
c.Log.Error(err, "error in getting account ID")
Expand All @@ -398,7 +399,7 @@ func (c *CloudflareAPI) GetTunnelCreds(tunnelSecret string) (string, error) {
return string(creds), err
}

// Get Zone Id from DNS domain
// GetZoneId gets Zone Id from DNS domain
func (c *CloudflareAPI) GetZoneId() (string, error) {
if c.ValidZoneId != "" {
return c.ValidZoneId, nil
Expand Down Expand Up @@ -452,7 +453,7 @@ func (c *CloudflareAPI) getZoneIdByName() (string, error) {
}
}

// Upsert DNS CNAME record for the given FQDN to point to the tunnel
// InsertOrUpdateCName upsert DNS CNAME record for the given FQDN to point to the tunnel
func (c *CloudflareAPI) InsertOrUpdateCName(fqdn string) error {
method := "POST"
subPath := ""
Expand Down Expand Up @@ -503,7 +504,7 @@ func (c *CloudflareAPI) InsertOrUpdateCName(fqdn string) error {
return nil
}

// Delete DNS CNAME entry for the given FQDN
// DeleteDNSCName deletes DNS CNAME entry for the given FQDN
func (c *CloudflareAPI) DeleteDNSCName(fqdn string) error {
dnsId, err := c.getDNSCNameId(fqdn)
if err != nil {
Expand Down
10 changes: 5 additions & 5 deletions controllers/cloudflare_configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"time"
)

// cloudflared configuration yaml model
// Configuration is a cloudflared configuration yaml model
type Configuration struct {
TunnelId string `yaml:"tunnel"`
Ingress []UnvalidatedIngressRule `yaml:"ingress,omitempty"`
Expand All @@ -15,20 +15,20 @@ type Configuration struct {
NoAutoUpdate bool `yaml:"no-autoupdate,omitempty"`
}

// cloudflared ingress entry model
// UnvalidatedIngressRule is a cloudflared ingress entry model
type UnvalidatedIngressRule struct {
Hostname string `yaml:"hostname,omitempty"`
Path string `yaml:"path,omitempty"`
Service string
OriginRequest OriginRequestConfig `yaml:"originRequest,omitempty"`
}

// cloudflared warp routing model
// WarpRoutingConfig is a cloudflared warp routing model
type WarpRoutingConfig struct {
Enabled bool `yaml:"enabled,omitempty"`
}

// cloudflared origin request configuration model
// OriginRequestConfig is a cloudflared origin request configuration model
type OriginRequestConfig struct {
// HTTP proxy timeout for establishing a new connection
ConnectTimeout *time.Duration `yaml:"connectTimeout,omitempty"`
Expand Down Expand Up @@ -68,7 +68,7 @@ type OriginRequestConfig struct {
IPRules []IngressIPRule `yaml:"ipRules,omitempty"`
}

// cloudflared origin ingress IP rule config model
// IngressIPRule is a cloudflared origin ingress IP rule config model
type IngressIPRule struct {
Prefix *string `yaml:"prefix,omitempty"`
Ports []int `yaml:"ports,omitempty"`
Expand Down
13 changes: 9 additions & 4 deletions controllers/service_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,11 @@ func (r *ServiceReconciler) initStruct(ctx context.Context, service *corev1.Serv
//+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;update;patch
//+kubebuilder:rbac:groups="",resources=events,verbs=create;patch

// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
//
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/reconcile
func (r *ServiceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
r.log = ctrllog.FromContext(ctx)

Expand Down Expand Up @@ -238,10 +243,10 @@ func (r *ServiceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
// Check if Service is marked for deletion
if r.service.GetDeletionTimestamp() != nil {
return ctrl.Result{}, r.deletionLogic()
} else {
if err := r.creationLogic(); err != nil {
return ctrl.Result{}, err
}
}

if err := r.creationLogic(); err != nil {
return ctrl.Result{}, err
}

// Configure ConfigMap
Expand Down
98 changes: 58 additions & 40 deletions controllers/tunnel_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,55 +160,54 @@ func (r *TunnelReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr
return ctrl.Result{}, err
}

okNewTunnel := tunnel.Spec.NewTunnel != networkingv1alpha1.NewTunnel{}
okExistingTunnel := tunnel.Spec.ExistingTunnel != networkingv1alpha1.ExistingTunnel{}
if res, ok, err := r.setupTunnel(); !ok {
return res, err
}

// Update status
if err := r.updateTunnelStatus(); err != nil {
return ctrl.Result{}, err
}

// Create necessary resources
if res, ok, err := r.createManagedResources(); !ok {
return res, err
}

return ctrl.Result{}, nil
}

func (r *TunnelReconciler) setupTunnel() (ctrl.Result, bool, error) {
okNewTunnel := r.tunnel.Spec.NewTunnel != networkingv1alpha1.NewTunnel{}
okExistingTunnel := r.tunnel.Spec.ExistingTunnel != networkingv1alpha1.ExistingTunnel{}

// If both are set (or neither are), we have a problem
if okNewTunnel == okExistingTunnel {
err := fmt.Errorf("spec ExistingTunnel and NewTunnel cannot be both empty and are mutually exclusive")
r.log.Error(err, "spec ExistingTunnel and NewTunnel cannot be both empty and are mutually exclusive")
r.Recorder.Event(tunnel, corev1.EventTypeWarning, "ErrSpecTunnel", "ExistingTunnel and NewTunnel cannot be both empty and are mutually exclusive")
return ctrl.Result{}, err
r.Recorder.Event(r.tunnel, corev1.EventTypeWarning, "ErrSpecTunnel", "ExistingTunnel and NewTunnel cannot be both empty and are mutually exclusive")
return ctrl.Result{}, false, err
}

if okExistingTunnel {
// Existing Tunnel, Set tunnelId in status and get creds file
if err := r.setupExistingTunnel(); err != nil {
return ctrl.Result{}, err
return ctrl.Result{}, false, err
}
} else {
// New tunnel, finalizer/cleanup logic + creation
if r.tunnel.GetDeletionTimestamp() != nil {
if res, err := r.cleanupTunnel(); err != nil || (res != ctrl.Result{}) {
return res, err
if res, ok, err := r.cleanupTunnel(); !ok {
return res, false, err
}
} else {
if err := r.setupNewTunnel(); err != nil {
return ctrl.Result{}, err
return ctrl.Result{}, false, err
}
}
}

// Update status
if err := r.updateTunnelStatus(); err != nil {
return ctrl.Result{}, err
}

// Check if Secret already exists, else create it
if err := r.createManagedSecret(); err != nil {
return ctrl.Result{}, err
}

// Check if ConfigMap already exists, else create it
if err := r.createManagedConfigMap(); err != nil {
return ctrl.Result{}, err
}

// Create Deployment if does not exist and scale it
if res, err := r.createOrScaleManagedDeployment(); err != nil || (res != ctrl.Result{}) {
return res, err
}

return ctrl.Result{}, nil
return ctrl.Result{}, true, nil
}

func (r *TunnelReconciler) setupExistingTunnel() error {
Expand Down Expand Up @@ -269,7 +268,7 @@ func (r *TunnelReconciler) setupNewTunnel() error {
return nil
}

func (r *TunnelReconciler) cleanupTunnel() (ctrl.Result, error) {
func (r *TunnelReconciler) cleanupTunnel() (ctrl.Result, bool, error) {
if controllerutil.ContainsFinalizer(r.tunnel, tunnelFinalizerAnnotation) {
// Run finalization logic. If the finalization logic fails,
// don't remove the finalizer so that we can retry during the next reconciliation.
Expand All @@ -290,16 +289,16 @@ func (r *TunnelReconciler) cleanupTunnel() (ctrl.Result, error) {
if err := r.Update(r.ctx, cfDeployment); err != nil {
r.log.Error(err, "Failed to update Deployment", "Deployment.Namespace", cfDeployment.Namespace, "Deployment.Name", cfDeployment.Name)
r.Recorder.Event(r.tunnel, corev1.EventTypeWarning, "FailedScaling", "Failed to scale down cloudflared")
return ctrl.Result{}, err
return ctrl.Result{}, false, err
}
r.log.Info("Scaling down successful", "size", r.tunnel.Spec.Size)
r.Recorder.Event(r.tunnel, corev1.EventTypeNormal, "Scaled", "Scaling down cloudflared successful")
return ctrl.Result{RequeueAfter: 5 * time.Second}, nil
return ctrl.Result{RequeueAfter: 5 * time.Second}, false, nil
}
if bypass || *cfDeployment.Spec.Replicas == 0 {
if err := r.cfAPI.DeleteCloudflareTunnel(); err != nil {
r.Recorder.Event(r.tunnel, corev1.EventTypeWarning, "FailedDeleting", "Tunnel deletion failed")
return ctrl.Result{}, err
return ctrl.Result{}, false, err
}
r.log.Info("Tunnel deleted", "tunnelID", r.tunnel.Status.TunnelId)
r.Recorder.Event(r.tunnel, corev1.EventTypeNormal, "Deleted", "Tunnel deletion successful")
Expand All @@ -311,13 +310,13 @@ func (r *TunnelReconciler) cleanupTunnel() (ctrl.Result, error) {
if err != nil {
r.log.Error(err, "unable to continue with tunnel deletion")
r.Recorder.Event(r.tunnel, corev1.EventTypeWarning, "FailedFinalizerUnset", "Unable to remove Tunnel Finalizer")
return ctrl.Result{}, err
return ctrl.Result{}, false, err
}
r.Recorder.Event(r.tunnel, corev1.EventTypeNormal, "FinalizerUnset", "Tunnel Finalizer removed")
return ctrl.Result{}, nil
return ctrl.Result{}, true, nil
}
}
return ctrl.Result{}, nil
return ctrl.Result{}, true, nil
}

func (r *TunnelReconciler) updateTunnelStatus() error {
Expand Down Expand Up @@ -390,19 +389,19 @@ func (r *TunnelReconciler) createManagedConfigMap() error {
return nil
}

func (r *TunnelReconciler) createOrScaleManagedDeployment() (ctrl.Result, error) {
func (r *TunnelReconciler) createOrScaleManagedDeployment() (ctrl.Result, bool, error) {
// Check if Deployment already exists, else create it
cfDeployment := &appsv1.Deployment{}
if res, err := r.createManagedDeployment(cfDeployment); err != nil || (res != ctrl.Result{}) {
return res, err
return res, false, err
}

// Ensure the Deployment size is the same as the spec
if res, err := r.scaleManagedDeployment(cfDeployment); err != nil || (res != ctrl.Result{}) {
return res, err
return res, false, err
}

return ctrl.Result{}, nil
return ctrl.Result{}, true, nil
}

func (r *TunnelReconciler) createManagedDeployment(cfDeployment *appsv1.Deployment) (ctrl.Result, error) {
Expand Down Expand Up @@ -449,6 +448,25 @@ func (r *TunnelReconciler) scaleManagedDeployment(cfDeployment *appsv1.Deploymen
return ctrl.Result{}, nil
}

func (r *TunnelReconciler) createManagedResources() (ctrl.Result, bool, error) {
// Check if Secret already exists, else create it
if err := r.createManagedSecret(); err != nil {
return ctrl.Result{}, false, err
}

// Check if ConfigMap already exists, else create it
if err := r.createManagedConfigMap(); err != nil {
return ctrl.Result{}, false, err
}

// Create Deployment if does not exist and scale it
if res, ok, err := r.createOrScaleManagedDeployment(); !ok {
return res, false, err
}

return ctrl.Result{}, true, nil
}

// configMapForTunnel returns a tunnel ConfigMap object
func (r *TunnelReconciler) configMapForTunnel(cfTunnel *networkingv1alpha1.Tunnel) *corev1.ConfigMap {
ls := labelsForTunnel(*cfTunnel)
Expand Down

0 comments on commit 2b176c6

Please sign in to comment.