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: ¤t.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: ¤t.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 }