github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/offering/openshift/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 openshiftorderer
    20  
    21  import (
    22  	"context"
    23  	"fmt"
    24  
    25  	current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1"
    26  	commoninit "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/common"
    27  	k8sclient "github.com/IBM-Blockchain/fabric-operator/pkg/k8s/controllerclient"
    28  	"github.com/IBM-Blockchain/fabric-operator/pkg/manager/resources"
    29  	resourcemanager "github.com/IBM-Blockchain/fabric-operator/pkg/manager/resources/manager"
    30  	baseorderer "github.com/IBM-Blockchain/fabric-operator/pkg/offering/base/orderer"
    31  	"github.com/IBM-Blockchain/fabric-operator/pkg/offering/common"
    32  	"github.com/IBM-Blockchain/fabric-operator/pkg/offering/openshift/orderer/override"
    33  	"github.com/IBM-Blockchain/fabric-operator/pkg/operatorerrors"
    34  	"github.com/IBM-Blockchain/fabric-operator/version"
    35  	routev1 "github.com/openshift/api/route/v1"
    36  	"github.com/pkg/errors"
    37  	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    38  	"sigs.k8s.io/controller-runtime/pkg/client"
    39  	"sigs.k8s.io/controller-runtime/pkg/reconcile"
    40  )
    41  
    42  type Override interface {
    43  	baseorderer.Override
    44  	OrdererRoute(object v1.Object, route *routev1.Route, action resources.Action) error
    45  	OperationsRoute(object v1.Object, route *routev1.Route, action resources.Action) error
    46  	AdminRoute(object v1.Object, route *routev1.Route, action resources.Action) error
    47  	OrdererGRPCRoute(object v1.Object, route *routev1.Route, action resources.Action) error
    48  }
    49  
    50  var _ baseorderer.IBPOrderer = &Node{}
    51  
    52  type Node struct {
    53  	*baseorderer.Node
    54  
    55  	RouteManager           resources.Manager
    56  	OperationsRouteManager resources.Manager
    57  	AdminRouteManager      resources.Manager
    58  	GRPCRouteManager       resources.Manager
    59  
    60  	Override Override
    61  }
    62  
    63  func NewNode(basenode *baseorderer.Node) *Node {
    64  	node := &Node{
    65  		Node:     basenode,
    66  		Override: &override.Override{},
    67  	}
    68  	node.CreateManagers()
    69  	return node
    70  }
    71  
    72  func (n *Node) CreateManagers() {
    73  	resourceManager := resourcemanager.New(n.Node.Client, n.Node.Scheme)
    74  	n.RouteManager = resourceManager.CreateRouteManager("", n.Override.OrdererRoute, n.GetLabels, n.Config.OrdererInitConfig.RouteFile)
    75  	n.OperationsRouteManager = resourceManager.CreateRouteManager("", n.Override.OperationsRoute, n.GetLabels, n.Config.OrdererInitConfig.RouteFile)
    76  	n.AdminRouteManager = resourceManager.CreateRouteManager("", n.Override.AdminRoute, n.GetLabels, n.Config.OrdererInitConfig.RouteFile)
    77  	n.GRPCRouteManager = resourceManager.CreateRouteManager("", n.Override.OrdererGRPCRoute, n.GetLabels, n.Config.OrdererInitConfig.RouteFile)
    78  }
    79  
    80  func (n *Node) Reconcile(instance *current.IBPOrderer, update baseorderer.Update) (common.Result, error) {
    81  	var err error
    82  	var status *current.CRStatus
    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  	var err error
   227  
   228  	err = n.Node.ReconcileManagers(instance, updated, genesisBlock)
   229  	if err != nil {
   230  		return err
   231  	}
   232  
   233  	update := updated.SpecUpdated()
   234  
   235  	err = n.RouteManager.Reconcile(instance, update)
   236  	if err != nil {
   237  		return errors.Wrap(err, "failed Orderer Route reconciliation")
   238  	}
   239  
   240  	err = n.OperationsRouteManager.Reconcile(instance, update)
   241  	if err != nil {
   242  		return errors.Wrap(err, "failed Operations Route reconciliation")
   243  	}
   244  
   245  	err = n.GRPCRouteManager.Reconcile(instance, update)
   246  	if err != nil {
   247  		return errors.Wrap(err, "failed Orderer GRPC Route reconciliation")
   248  	}
   249  
   250  	currentVer := version.String(instance.Spec.FabricVersion)
   251  	if currentVer.EqualWithoutTag(version.V2_4_1) || currentVer.GreaterThan(version.V2_4_1) {
   252  		err = n.AdminRouteManager.Reconcile(instance, update)
   253  		if err != nil {
   254  			return errors.Wrap(err, "failed Orderer Admin Route reconciliation")
   255  		}
   256  	}
   257  
   258  	return nil
   259  }