github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/offering/k8s/orderer/node.go (about)

     1  /*
     2   * Copyright contributors to the Hyperledger Fabric Operator project
     3   *
     4   * SPDX-License-Identifier: Apache-2.0
     5   *
     6   * Licensed under the Apache License, Version 2.0 (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at:
     9   *
    10   * 	  http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing, software
    13   * distributed under the License is distributed on an "AS IS" BASIS,
    14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15   * See the License for the specific language governing permissions and
    16   * limitations under the License.
    17   */
    18  
    19  package k8sorderer
    20  
    21  import (
    22  	"context"
    23  	"fmt"
    24  	"strings"
    25  
    26  	current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1"
    27  	commoninit "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/common"
    28  	k8sclient "github.com/IBM-Blockchain/fabric-operator/pkg/k8s/controllerclient"
    29  	"github.com/IBM-Blockchain/fabric-operator/pkg/manager/resources"
    30  	resourcemanager "github.com/IBM-Blockchain/fabric-operator/pkg/manager/resources/manager"
    31  	baseorderer "github.com/IBM-Blockchain/fabric-operator/pkg/offering/base/orderer"
    32  	"github.com/IBM-Blockchain/fabric-operator/pkg/offering/common"
    33  	"github.com/IBM-Blockchain/fabric-operator/pkg/offering/k8s/orderer/override"
    34  	"github.com/IBM-Blockchain/fabric-operator/pkg/operatorerrors"
    35  	"github.com/IBM-Blockchain/fabric-operator/pkg/util"
    36  	"github.com/IBM-Blockchain/fabric-operator/version"
    37  	"github.com/pkg/errors"
    38  	networkingv1 "k8s.io/api/networking/v1"
    39  	networkingv1beta1 "k8s.io/api/networking/v1beta1"
    40  	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    41  	"sigs.k8s.io/controller-runtime/pkg/client"
    42  	"sigs.k8s.io/controller-runtime/pkg/reconcile"
    43  )
    44  
    45  type Override interface {
    46  	baseorderer.Override
    47  	Ingress(v1.Object, *networkingv1.Ingress, resources.Action) error
    48  	Ingressv1beta1(v1.Object, *networkingv1beta1.Ingress, resources.Action) error
    49  }
    50  
    51  var _ baseorderer.IBPOrderer = &Node{}
    52  
    53  type Node struct {
    54  	*baseorderer.Node
    55  
    56  	IngressManager        resources.Manager
    57  	Ingressv1beta1Manager resources.Manager
    58  
    59  	Override Override
    60  }
    61  
    62  func NewNode(basenode *baseorderer.Node) *Node {
    63  	node := &Node{
    64  		Node:     basenode,
    65  		Override: &override.Override{},
    66  	}
    67  	node.CreateManagers()
    68  	return node
    69  }
    70  
    71  func (n *Node) CreateManagers() {
    72  	override := n.Override
    73  	resourceManager := resourcemanager.New(n.Client, n.Scheme)
    74  	n.IngressManager = resourceManager.CreateIngressManager("", override.Ingress, n.GetLabels, n.Config.OrdererInitConfig.IngressFile)
    75  	n.Ingressv1beta1Manager = resourceManager.CreateIngressv1beta1Manager("", override.Ingressv1beta1, n.GetLabels, n.Config.OrdererInitConfig.Ingressv1beta1File)
    76  }
    77  
    78  func (n *Node) Reconcile(instance *current.IBPOrderer, update baseorderer.Update) (common.Result, error) {
    79  	var err error
    80  	var status *current.CRStatus
    81  
    82  	log.Info(fmt.Sprintf("Reconciling node instance '%s' ... update: %+v", instance.Name, update))
    83  
    84  	versionSet, err := n.SetVersion(instance)
    85  	if err != nil {
    86  		return common.Result{}, errors.Wrap(err, fmt.Sprintf("failed updating CR '%s' to version '%s'", instance.Name, version.Operator))
    87  	}
    88  	if versionSet {
    89  		log.Info("Instance version updated, requeuing request...")
    90  		return common.Result{
    91  			Result: reconcile.Result{
    92  				Requeue: true,
    93  			},
    94  			OverrideUpdateStatus: true,
    95  		}, nil
    96  	}
    97  
    98  	instanceUpdated, err := n.PreReconcileChecks(instance, update)
    99  	if err != nil {
   100  		return common.Result{}, errors.Wrap(err, "failed pre reconcile checks")
   101  	}
   102  	externalEndpointUpdated := n.UpdateExternalEndpoint(instance)
   103  
   104  	if instanceUpdated || externalEndpointUpdated {
   105  		log.Info(fmt.Sprintf("Updating instance after pre reconcile checks: %t, updating external endpoint: %t",
   106  			instanceUpdated, externalEndpointUpdated))
   107  
   108  		err = n.Client.Patch(context.TODO(), instance, nil, k8sclient.PatchOption{
   109  			Resilient: &k8sclient.ResilientPatch{
   110  				Retry:    3,
   111  				Into:     &current.IBPOrderer{},
   112  				Strategy: client.MergeFrom,
   113  			},
   114  		})
   115  		if err != nil {
   116  			return common.Result{}, errors.Wrap(err, "failed to update instance")
   117  		}
   118  
   119  		log.Info("Instance updated during reconcile checks, request will be requeued...")
   120  		return common.Result{
   121  			Result: reconcile.Result{
   122  				Requeue: true,
   123  			},
   124  			Status: &current.CRStatus{
   125  				Type:    current.Initializing,
   126  				Reason:  "Setting default values for either zone, region, and/or external endpoint",
   127  				Message: "Operator has updated spec with defaults as part of initialization",
   128  			},
   129  			OverrideUpdateStatus: true,
   130  		}, nil
   131  	}
   132  
   133  	err = n.Initialize(instance, update)
   134  	if err != nil {
   135  		return common.Result{}, operatorerrors.Wrap(err, operatorerrors.OrdererInitilizationFailed, "failed to initialize orderer node")
   136  	}
   137  
   138  	if update.OrdererTagUpdated() {
   139  		if err := n.ReconcileFabricOrdererMigration(instance); err != nil {
   140  			return common.Result{}, operatorerrors.Wrap(err, operatorerrors.FabricOrdererMigrationFailed, "failed to migrate fabric orderer versions")
   141  		}
   142  	}
   143  
   144  	if update.MigrateToV2() {
   145  		if err := n.FabricOrdererMigrationV2_0(instance); err != nil {
   146  			return common.Result{}, operatorerrors.Wrap(err, operatorerrors.FabricOrdererMigrationFailed, "failed to migrate fabric orderer to version v2.x")
   147  		}
   148  	}
   149  
   150  	if update.MigrateToV24() {
   151  		if err := n.FabricOrdererMigrationV2_4(instance); err != nil {
   152  			return common.Result{}, operatorerrors.Wrap(err, operatorerrors.FabricOrdererMigrationFailed, "failed to migrate fabric orderer to version v2.4.x")
   153  		}
   154  	}
   155  
   156  	err = n.ReconcileManagers(instance, update, nil)
   157  	if err != nil {
   158  		return common.Result{}, errors.Wrap(err, "failed to reconcile managers")
   159  	}
   160  
   161  	err = n.UpdateConnectionProfile(instance)
   162  	if err != nil {
   163  		return common.Result{}, errors.Wrap(err, "failed to create connection profile")
   164  	}
   165  
   166  	err = n.CheckStates(instance)
   167  	if err != nil {
   168  		return common.Result{}, errors.Wrap(err, "failed to check and restore state")
   169  	}
   170  
   171  	err = n.UpdateParentStatus(instance)
   172  	if err != nil {
   173  		return common.Result{}, errors.Wrap(err, "failed to update parent's status")
   174  	}
   175  
   176  	status, result, err := n.CustomLogic(instance, update)
   177  	if err != nil {
   178  		return common.Result{}, errors.Wrap(err, "failed to run custom offering logic		")
   179  	}
   180  	if result != nil {
   181  		log.Info(fmt.Sprintf("Finished reconciling '%s' with Custom Logic result", instance.GetName()))
   182  		return *result, nil
   183  	}
   184  
   185  	if update.EcertUpdated() {
   186  		log.Info("Ecert was updated")
   187  		// Request deployment restart for tls cert update
   188  		err = n.Restart.ForCertUpdate(commoninit.ECERT, instance)
   189  		if err != nil {
   190  			return common.Result{}, errors.Wrap(err, "failed to update restart config")
   191  		}
   192  	}
   193  
   194  	if update.TLSCertUpdated() {
   195  		log.Info("TLS cert was updated")
   196  		// Request deployment restart for ecert update
   197  		err = n.Restart.ForCertUpdate(commoninit.TLS, instance)
   198  		if err != nil {
   199  			return common.Result{}, errors.Wrap(err, "failed to update restart config")
   200  		}
   201  	}
   202  
   203  	if update.MSPUpdated() {
   204  		err = n.UpdateMSPCertificates(instance)
   205  		if err != nil {
   206  			if err != nil {
   207  				return common.Result{}, errors.Wrap(err, "failed to update certificates passed in MSP spec")
   208  			}
   209  		}
   210  	}
   211  
   212  	if err := n.HandleActions(instance, update); err != nil {
   213  		return common.Result{}, err
   214  	}
   215  
   216  	if err := n.HandleRestart(instance, update); err != nil {
   217  		return common.Result{}, err
   218  	}
   219  
   220  	return common.Result{
   221  		Status: status,
   222  	}, nil
   223  }
   224  
   225  func (n *Node) ReconcileManagers(instance *current.IBPOrderer, updated baseorderer.Update, genesisBlock []byte) error {
   226  	err := n.Node.ReconcileManagers(instance, updated, genesisBlock)
   227  	if err != nil {
   228  		return err
   229  	}
   230  
   231  	update := updated.SpecUpdated()
   232  
   233  	err = n.ReconcileIngressManager(instance, update)
   234  	if err != nil {
   235  		return errors.Wrap(err, "failed Ingress reconciliation")
   236  	}
   237  
   238  	return nil
   239  }
   240  
   241  func (n *Node) ReconcileIngressManager(instance *current.IBPOrderer, update bool) error {
   242  	if n.Config.Operator.Globals.AllowKubernetesEighteen == "true" {
   243  		// check k8s version
   244  		version, err := util.GetServerVersion()
   245  		if err != nil {
   246  			return err
   247  		}
   248  		if strings.Compare(version.Minor, "19") < 0 { // v1beta
   249  			err = n.Ingressv1beta1Manager.Reconcile(instance, update)
   250  			if err != nil {
   251  				return errors.Wrap(err, "failed Ingressv1beta1 reconciliation")
   252  			}
   253  		} else {
   254  			err = n.IngressManager.Reconcile(instance, update)
   255  			if err != nil {
   256  				return errors.Wrap(err, "failed Ingress reconciliation")
   257  			}
   258  		}
   259  	} else {
   260  		err := n.IngressManager.Reconcile(instance, update)
   261  		if err != nil {
   262  			return errors.Wrap(err, "failed Ingress reconciliation")
   263  		}
   264  	}
   265  	return nil
   266  }