github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/offering/openshift/ca/ca.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 openshiftca
    20  
    21  import (
    22  	"context"
    23  	"fmt"
    24  
    25  	current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1"
    26  	config "github.com/IBM-Blockchain/fabric-operator/operatorconfig"
    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  	baseca "github.com/IBM-Blockchain/fabric-operator/pkg/offering/base/ca"
    31  	basecaoverride "github.com/IBM-Blockchain/fabric-operator/pkg/offering/base/ca/override"
    32  	"github.com/IBM-Blockchain/fabric-operator/pkg/offering/common"
    33  	"github.com/IBM-Blockchain/fabric-operator/pkg/offering/openshift/ca/override"
    34  	"github.com/IBM-Blockchain/fabric-operator/pkg/operatorerrors"
    35  	"github.com/IBM-Blockchain/fabric-operator/version"
    36  	routev1 "github.com/openshift/api/route/v1"
    37  	"github.com/pkg/errors"
    38  	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    39  	"k8s.io/apimachinery/pkg/runtime"
    40  	"sigs.k8s.io/controller-runtime/pkg/client"
    41  	logf "sigs.k8s.io/controller-runtime/pkg/log"
    42  	"sigs.k8s.io/controller-runtime/pkg/reconcile"
    43  )
    44  
    45  var log = logf.Log.WithName("openshift_ca")
    46  
    47  type Override interface {
    48  	baseca.Override
    49  	CARoute(object v1.Object, route *routev1.Route, action resources.Action) error
    50  	OperationsRoute(object v1.Object, route *routev1.Route, action resources.Action) error
    51  }
    52  
    53  var _ baseca.IBPCA = &CA{}
    54  
    55  type CA struct {
    56  	*baseca.CA
    57  
    58  	CARouteManager         resources.Manager
    59  	OperationsRouteManager resources.Manager
    60  
    61  	Override Override
    62  }
    63  
    64  func New(client k8sclient.Client, scheme *runtime.Scheme, config *config.Config) *CA {
    65  	o := &override.Override{
    66  		Override: basecaoverride.Override{
    67  			Client: client,
    68  		},
    69  	}
    70  	ca := &CA{
    71  		CA:       baseca.New(client, scheme, config, o),
    72  		Override: o,
    73  	}
    74  	ca.CreateManagers()
    75  	return ca
    76  }
    77  
    78  func (ca *CA) CreateManagers() {
    79  	resourceManager := resourcemanager.New(ca.Client, ca.Scheme)
    80  	ca.CARouteManager = resourceManager.CreateRouteManager("ca", ca.Override.CARoute, ca.GetLabels, ca.Config.CAInitConfig.RouteFile)
    81  	ca.OperationsRouteManager = resourceManager.CreateRouteManager("operations", ca.Override.OperationsRoute, ca.GetLabels, ca.Config.CAInitConfig.RouteFile)
    82  }
    83  
    84  func (ca *CA) Reconcile(instance *current.IBPCA, update baseca.Update) (common.Result, error) {
    85  
    86  	var err error
    87  
    88  	versionSet, err := ca.SetVersion(instance)
    89  	if err != nil {
    90  		return common.Result{}, errors.Wrap(err, fmt.Sprintf("failed updating CR '%s' to version '%s'", instance.Name, version.Operator))
    91  	}
    92  	if versionSet {
    93  		log.Info("Instance version updated, requeuing request...")
    94  		return common.Result{
    95  			Result: reconcile.Result{
    96  				Requeue: true,
    97  			},
    98  		}, nil
    99  	}
   100  
   101  	instanceUpdated, err := ca.PreReconcileChecks(instance, update)
   102  	if err != nil {
   103  		return common.Result{}, errors.Wrap(err, "failed pre reconcile checks")
   104  	}
   105  
   106  	if instanceUpdated {
   107  		log.Info("Updating instance after pre reconcile checks")
   108  		err := ca.Client.Patch(context.TODO(), instance, nil, k8sclient.PatchOption{
   109  			Resilient: &k8sclient.ResilientPatch{
   110  				Retry:    3,
   111  				Into:     &current.IBPCA{},
   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, requeuing request...")
   120  		return common.Result{
   121  			Result: reconcile.Result{
   122  				Requeue: true,
   123  			},
   124  		}, nil
   125  	}
   126  
   127  	err = ca.AddTLSCryptoIfMissing(instance, ca.GetEndpointsDNS(instance))
   128  	if err != nil {
   129  		return common.Result{}, errors.Wrap(err, "failed to generate tls crypto")
   130  	}
   131  
   132  	err = ca.Initialize(instance, update)
   133  	if err != nil {
   134  		return common.Result{}, operatorerrors.Wrap(err, operatorerrors.CAInitilizationFailed, "failed to initialize ca")
   135  	}
   136  
   137  	err = ca.ReconcileManagers(instance, update)
   138  	if err != nil {
   139  		return common.Result{}, errors.Wrap(err, "failed to reconcile managers")
   140  	}
   141  
   142  	if update.CATagUpdated() {
   143  		if err := ca.ReconcileFabricCAMigration(instance); err != nil {
   144  			return common.Result{}, operatorerrors.Wrap(err, operatorerrors.FabricCAMigrationFailed, "failed to migrate fabric ca versions")
   145  		}
   146  	}
   147  
   148  	err = ca.UpdateConnectionProfile(instance)
   149  	if err != nil {
   150  		return common.Result{}, errors.Wrap(err, "failed to create connection profile")
   151  	}
   152  
   153  	err = ca.CheckStates(instance)
   154  	if err != nil {
   155  		return common.Result{}, errors.Wrap(err, "failed to check and restore state")
   156  	}
   157  
   158  	status, err := ca.CheckCertificates(instance)
   159  	if err != nil {
   160  		return common.Result{}, errors.Wrap(err, "failed to check for expiring certificates")
   161  	}
   162  
   163  	if update.CACryptoUpdated() {
   164  		err = ca.Restart.ForTLSReenroll(instance)
   165  		if err != nil {
   166  			return common.Result{}, errors.Wrap(err, "failed to update restart config")
   167  		}
   168  	}
   169  
   170  	err = ca.HandleActions(instance, update)
   171  	if err != nil {
   172  		return common.Result{}, err
   173  	}
   174  
   175  	err = ca.HandleRestart(instance, update)
   176  	if err != nil {
   177  		return common.Result{}, err
   178  	}
   179  
   180  	return common.Result{
   181  		Status: status,
   182  	}, nil
   183  }
   184  
   185  func (ca *CA) ReconcileManagers(instance *current.IBPCA, update baseca.Update) error {
   186  	err := ca.CA.ReconcileManagers(instance, update)
   187  	if err != nil {
   188  		return err
   189  	}
   190  
   191  	err = ca.CARouteManager.Reconcile(instance, update.SpecUpdated())
   192  	if err != nil {
   193  		return errors.Wrap(err, "failed CA Route reconciliation")
   194  	}
   195  
   196  	err = ca.OperationsRouteManager.Reconcile(instance, update.SpecUpdated())
   197  	if err != nil {
   198  		return errors.Wrap(err, "failed Operations Route reconciliation")
   199  	}
   200  
   201  	return nil
   202  }