Skip to content

Commit

Permalink
account controller
Browse files Browse the repository at this point in the history
  • Loading branch information
eguzki committed Dec 24, 2020
1 parent fab34bf commit 118880a
Show file tree
Hide file tree
Showing 4 changed files with 204 additions and 0 deletions.
19 changes: 19 additions & 0 deletions apis/capabilities/v1beta1/account_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/go-logr/logr"
"github.com/google/go-cmp/cmp"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/validation/field"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
Expand Down Expand Up @@ -71,6 +72,12 @@ type AccountStatus struct {
// +optional
ID *int64 `json:"accountID,omitempty"`

// +optional
AccountState *string `json:"accountState,omitempty"`

// +optional
CreditCardStored *bool `json:"creditCardStored,omitempty"`

// ProviderAccountHost contains the 3scale account's provider URL
// +optional
ProviderAccountHost string `json:"providerAccountHost,omitempty"`
Expand Down Expand Up @@ -100,6 +107,18 @@ func (a *AccountStatus) Equals(other *AccountStatus, logger logr.Logger) bool {
return false
}

if !reflect.DeepEqual(a.AccountState, other.AccountState) {
diff := cmp.Diff(a.AccountState, other.AccountState)
logger.V(1).Info("AccountState not equal", "difference", diff)
return false
}

if !reflect.DeepEqual(a.CreditCardStored, other.CreditCardStored) {
diff := cmp.Diff(a.CreditCardStored, other.CreditCardStored)
logger.V(1).Info("CreditCardStored not equal", "difference", diff)
return false
}

if a.ObservedGeneration != other.ObservedGeneration {
diff := cmp.Diff(a.ObservedGeneration, other.ObservedGeneration)
logger.V(1).Info("ObservedGeneration not equal", "difference", diff)
Expand Down
10 changes: 10 additions & 0 deletions apis/capabilities/v1beta1/zz_generated.deepcopy.go

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

139 changes: 139 additions & 0 deletions controllers/capabilities/account_status_reconciler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package controllers

import (
"fmt"

capabilitiesv1beta1 "github.com/3scale/3scale-operator/apis/capabilities/v1beta1"
"github.com/3scale/3scale-operator/pkg/common"
"github.com/3scale/3scale-operator/pkg/helper"
"github.com/3scale/3scale-operator/pkg/reconcilers"

threescaleapi "github.com/3scale/3scale-porta-go-client/client"
"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)

type AccountStatusReconciler struct {
*reconcilers.BaseReconciler
resource *capabilitiesv1beta1.Account
providerAccountHost string
remoteAccount *threescaleapi.DeveloperAccount
reconcileError error
logger logr.Logger
}

func NewAccountStatusReconciler(b *reconcilers.BaseReconciler, resource *capabilitiesv1beta1.Account, providerAccountHost string, remoteAccount *threescaleapi.DeveloperAccount, reconcileError error) *AccountStatusReconciler {
return &AccountStatusReconciler{
BaseReconciler: b,
resource: resource,
providerAccountHost: providerAccountHost,
remoteAccount: remoteAccount,
reconcileError: reconcileError,
logger: b.Logger().WithValues("Status Reconciler", resource.Name),
}
}

func (s *AccountStatusReconciler) Reconcile() (reconcile.Result, error) {
s.logger.V(1).Info("START")

newStatus, err := s.calculateStatus()
if err != nil {
return reconcile.Result{}, err
}

equalStatus := s.resource.Status.Equals(newStatus, s.logger)
s.logger.V(1).Info("Status", "status is different", !equalStatus)
s.logger.V(1).Info("Status", "generation is different", s.resource.Generation != s.resource.Status.ObservedGeneration)
if equalStatus && s.resource.Generation == s.resource.Status.ObservedGeneration {
// Steady state
s.logger.V(1).Info("Status steady state, status was not updated")
return reconcile.Result{}, nil
}

// Save the generation number we acted on, otherwise we might wrongfully indicate
// that we've seen a spec update when we retry.
// TODO: This can clobber an update if we allow multiple agents to write to the
// same status.
newStatus.ObservedGeneration = s.resource.Generation

s.logger.V(1).Info("Updating Status", "sequence no:", fmt.Sprintf("sequence No: %v->%v", s.resource.Status.ObservedGeneration, newStatus.ObservedGeneration))

s.resource.Status = *newStatus
updateErr := s.Client().Status().Update(s.Context(), s.resource)
if updateErr != nil {
// Ignore conflicts, resource might just be outdated.
if errors.IsConflict(updateErr) {
s.logger.Info("Failed to update status: resource might just be outdated")
return reconcile.Result{Requeue: true}, nil
}

return reconcile.Result{}, fmt.Errorf("Failed to update status: %w", updateErr)
}
return reconcile.Result{}, nil
}

func (s *AccountStatusReconciler) calculateStatus() (*capabilitiesv1beta1.AccountStatus, error) {
newStatus := &capabilitiesv1beta1.AccountStatus{}

if s.remoteAccount != nil {
newStatus.ID = s.remoteAccount.Element.ID
}

newStatus.AccountState = &s.remoteAccount.Element.State
newStatus.CreditCardStored = &s.remoteAccount.Element.CreditCardStored

newStatus.ProviderAccountHost = s.providerAccountHost

newStatus.ObservedGeneration = s.resource.Status.ObservedGeneration

newStatus.Conditions = s.resource.Status.Conditions.Copy()
newStatus.Conditions.SetCondition(s.readyCondition())
newStatus.Conditions.SetCondition(s.invalidCondition())
newStatus.Conditions.SetCondition(s.failedCondition())

return newStatus, nil
}

func (s *AccountStatusReconciler) readyCondition() common.Condition {
condition := common.Condition{
Type: capabilitiesv1beta1.AccountReadyConditionType,
Status: corev1.ConditionFalse,
}

if s.reconcileError == nil {
condition.Status = corev1.ConditionTrue
}

return condition
}

func (s *AccountStatusReconciler) invalidCondition() common.Condition {
condition := common.Condition{
Type: capabilitiesv1beta1.AccountInvalidConditionType,
Status: corev1.ConditionFalse,
}

if helper.IsInvalidSpecError(s.reconcileError) {
condition.Status = corev1.ConditionTrue
condition.Message = s.reconcileError.Error()
}

return condition
}

func (s *AccountStatusReconciler) failedCondition() common.Condition {
condition := common.Condition{
Type: capabilitiesv1beta1.AccountFailedConditionType,
Status: corev1.ConditionFalse,
}

// This condition could be activated together with other conditions
if s.reconcileError != nil {
condition.Status = corev1.ConditionTrue
condition.Message = s.reconcileError.Error()
}

return condition
}
36 changes: 36 additions & 0 deletions controllers/capabilities/account_threescale_reconciler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package controllers

import (
"encoding/json"
"reflect"

capabilitiesv1beta1 "github.com/3scale/3scale-operator/apis/capabilities/v1beta1"
"github.com/3scale/3scale-operator/pkg/reconcilers"

threescaleapi "github.com/3scale/3scale-porta-go-client/client"
"github.com/go-logr/logr"
"github.com/google/go-cmp/cmp"
)

type AccountThreescaleReconciler struct {
*reconcilers.BaseReconciler
resource *capabilitiesv1beta1.Account
threescaleAPIClient *threescaleapi.ThreeScaleClient
providerAccountHost string
logger logr.Logger
}

func NewAccountThreescaleReconciler(b *reconcilers.BaseReconciler, resource *capabilitiesv1beta1.Account, threescaleAPIClient *threescaleapi.ThreeScaleClient, providerAccountHost string, logger logr.Logger) *AccountThreescaleReconciler {
return &AccountThreescaleReconciler{
BaseReconciler: b,
resource: resource,
threescaleAPIClient: threescaleAPIClient,
providerAccountHost: providerAccountHost,
logger: logger.WithValues("3scale Reconciler", providerAccountHost),
}
}

func (s *AccountThreescaleReconciler) Reconcile() (*threescaleapi.DeveloperAccount, error) {
s.logger.V(1).Info("START")
return nil, nil
}

0 comments on commit 118880a

Please sign in to comment.