github.com/IBM-Blockchain/fabric-operator@v1.0.4/integration/operatorrestart/operatorrestart_suite_test.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 operatorrestart_test
    20  
    21  import (
    22  	"encoding/base64"
    23  	"fmt"
    24  	"io/ioutil"
    25  	"net/url"
    26  	"os"
    27  	"path/filepath"
    28  	"strings"
    29  	"testing"
    30  	"time"
    31  
    32  	. "github.com/onsi/ginkgo/v2"
    33  	. "github.com/onsi/gomega"
    34  	"github.com/onsi/gomega/gexec"
    35  
    36  	current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1"
    37  	"github.com/IBM-Blockchain/fabric-operator/integration"
    38  	"github.com/IBM-Blockchain/fabric-operator/integration/helper"
    39  	v1 "github.com/IBM-Blockchain/fabric-operator/pkg/apis/ca/v1"
    40  	ibpclient "github.com/IBM-Blockchain/fabric-operator/pkg/client"
    41  	"github.com/IBM-Blockchain/fabric-operator/pkg/command"
    42  	baseorderer "github.com/IBM-Blockchain/fabric-operator/pkg/offering/base/orderer"
    43  	"github.com/IBM-Blockchain/fabric-operator/pkg/util"
    44  	"github.com/IBM-Blockchain/fabric-operator/pkg/util/pointer"
    45  
    46  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    47  	"k8s.io/apimachinery/pkg/runtime"
    48  	"k8s.io/client-go/kubernetes"
    49  )
    50  
    51  func TestOperatorrestart(t *testing.T) {
    52  	RegisterFailHandler(Fail)
    53  	RunSpecs(t, "Operatorrestart Suite")
    54  }
    55  
    56  const (
    57  	ccTarFile = "gocc.tar.gz"
    58  
    59  	FabricBinaryVersion   = "2.2.3"
    60  	FabricCABinaryVersion = "1.5.1"
    61  
    62  	peerAdminUsername = "peer-admin"
    63  	peerUsername      = "peer"
    64  	ordererUsername   = "orderer"
    65  
    66  	IBPCAS      = "ibpcas"
    67  	IBPPEERS    = "ibppeers"
    68  	IBPORDERERS = "ibporderers"
    69  )
    70  
    71  var (
    72  	wd          string // Working directory of test
    73  	namespace   string
    74  	domain      string
    75  	kclient     *kubernetes.Clientset
    76  	ibpCRClient *ibpclient.IBPClient
    77  	colorIndex  uint
    78  	testFailed  bool
    79  	caHost      string
    80  	tlsBytes    []byte
    81  
    82  	org1ca   *helper.CA
    83  	org1peer *helper.Peer
    84  	orderer  *helper.Orderer
    85  )
    86  
    87  var _ = BeforeSuite(func() {
    88  	SetDefaultEventuallyTimeout(420 * time.Second)
    89  	SetDefaultEventuallyPollingInterval(time.Second)
    90  
    91  	var err error
    92  
    93  	domain = os.Getenv("DOMAIN")
    94  	if domain == "" {
    95  		domain = integration.TestAutomation1IngressDomain
    96  	}
    97  
    98  	wd, err = os.Getwd()
    99  	Expect(err).NotTo(HaveOccurred())
   100  	fmt.Fprintf(GinkgoWriter, "Working directory: %s\n", wd)
   101  
   102  	cleanupFiles()
   103  
   104  	cfg := &integration.Config{
   105  		OperatorServiceAccount: "../../config/rbac/service_account.yaml",
   106  		OperatorRole:           "../../config/rbac/role.yaml",
   107  		OperatorRoleBinding:    "../../config/rbac/role_binding.yaml",
   108  		OperatorDeployment:     "../../testdata/deploy/operator.yaml",
   109  		OrdererSecret:          "../../testdata/deploy/orderer/secret.yaml",
   110  		PeerSecret:             "../../testdata/deploy/peer/secret.yaml",
   111  		ConsoleTLSSecret:       "../../testdata/deploy/console/tlssecret.yaml",
   112  	}
   113  
   114  	namespace, kclient, ibpCRClient, err = integration.Setup(GinkgoWriter, cfg, "operatorrestart", "")
   115  
   116  	Expect(err).NotTo(HaveOccurred())
   117  
   118  	downloadBinaries()
   119  
   120  	CreateNetwork()
   121  })
   122  
   123  var _ = AfterSuite(func() {
   124  
   125  	if strings.ToLower(os.Getenv("SAVE_TEST")) == "true" {
   126  		return
   127  	}
   128  
   129  	integration.Cleanup(GinkgoWriter, kclient, namespace)
   130  
   131  	cleanupFiles()
   132  })
   133  
   134  func CreateNetwork() {
   135  	By("starting CA pod", func() {
   136  		org1ca = Org1CA()
   137  		helper.CreateCA(ibpCRClient, org1ca.CR)
   138  
   139  		Eventually(org1ca.PodIsRunning).Should((Equal(true)))
   140  	})
   141  
   142  	profile, err := org1ca.ConnectionProfile()
   143  	Expect(err).NotTo(HaveOccurred())
   144  
   145  	tlsBytes, err = util.Base64ToBytes(profile.TLS.Cert)
   146  	Expect(err).NotTo(HaveOccurred())
   147  
   148  	By("performing CA health check", func() {
   149  		Eventually(func() bool {
   150  			url := fmt.Sprintf("https://%s/cainfo", org1ca.Address())
   151  			fmt.Fprintf(GinkgoWriter, "Waiting for CA health check to pass for '%s' at url: %s\n", org1ca.Name, url)
   152  			return org1ca.HealthCheck(url, tlsBytes)
   153  		}).Should(Equal(true))
   154  	})
   155  
   156  	org1ca.TLSToFile(tlsBytes)
   157  
   158  	caURL, err := url.Parse(profile.Endpoints.API)
   159  	Expect(err).NotTo(HaveOccurred())
   160  	caHost = strings.Split(caURL.Host, ":")[0]
   161  
   162  	By("enrolling ca admin", func() {
   163  		os.Setenv("FABRIC_CA_CLIENT_HOME", filepath.Join(wd, org1ca.Name, "org1ca-admin"))
   164  		sess, err := helper.StartSession(org1ca.Enroll("admin", "adminpw"), "Enroll CA Admin")
   165  		Expect(err).NotTo(HaveOccurred())
   166  		Eventually(sess).Should(gexec.Exit(0))
   167  	})
   168  
   169  	By("registering peer identity", func() {
   170  		os.Setenv("FABRIC_CA_CLIENT_HOME", filepath.Join(wd, org1ca.Name, "org1ca-admin"))
   171  		sess, err := helper.StartSession(org1ca.Register(peerUsername, "peerpw", "peer"), "Register User")
   172  		Expect(err).NotTo(HaveOccurred())
   173  		Eventually(sess).Should(gexec.Exit(0))
   174  	})
   175  
   176  	By("registering and enrolling peer admin", func() {
   177  		os.Setenv("FABRIC_CA_CLIENT_HOME", filepath.Join(wd, org1ca.Name, "org1ca-admin"))
   178  		sess, err := helper.StartSession(org1ca.Register(peerAdminUsername, "peer-adminpw", "admin"), "Register Peer Admin")
   179  		Expect(err).NotTo(HaveOccurred())
   180  		Eventually(sess).Should(gexec.Exit(0))
   181  
   182  		os.Setenv("FABRIC_CA_CLIENT_HOME", filepath.Join(wd, "org1peer", peerAdminUsername))
   183  		sess, err = helper.StartSession(org1ca.Enroll(peerAdminUsername, "peer-adminpw"), "Enroll Peer Admin")
   184  		Expect(err).NotTo(HaveOccurred())
   185  		Eventually(sess).Should(gexec.Exit(0))
   186  	})
   187  
   188  	By("registering orderer identity", func() {
   189  		os.Setenv("FABRIC_CA_CLIENT_HOME", filepath.Join(wd, org1ca.Name, "org1ca-admin"))
   190  		sess, err := helper.StartSession(org1ca.Register(ordererUsername, "ordererpw", "orderer"), "Register Orderer Identity")
   191  		Expect(err).NotTo(HaveOccurred())
   192  		Eventually(sess).Should(gexec.Exit(0))
   193  
   194  		os.Setenv("FABRIC_CA_CLIENT_HOME", filepath.Join(wd, org1ca.Name, "org1ca-admin"))
   195  		sess, err = helper.StartSession(org1ca.Register("orderer2", "ordererpw2", "orderer"), "Register Orderer Identity")
   196  		Expect(err).NotTo(HaveOccurred())
   197  		Eventually(sess).Should(gexec.Exit(0))
   198  	})
   199  
   200  	adminCertBytes, err := ioutil.ReadFile(
   201  		filepath.Join(
   202  			wd,
   203  			"org1peer",
   204  			peerAdminUsername,
   205  			"msp",
   206  			"signcerts",
   207  			"cert.pem",
   208  		),
   209  	)
   210  	Expect(err).NotTo(HaveOccurred())
   211  	adminCertB64 := base64.StdEncoding.EncodeToString(adminCertBytes)
   212  	tlsCert := base64.StdEncoding.EncodeToString(tlsBytes)
   213  
   214  	By("starting Peer pod", func() {
   215  		org1peer = Org1Peer(tlsCert, caHost, adminCertB64)
   216  		err = helper.CreatePeer(ibpCRClient, org1peer.CR)
   217  		Expect(err).NotTo(HaveOccurred())
   218  	})
   219  
   220  	By("starting Orderer pod", func() {
   221  		orderer = GetOrderer(tlsCert, caHost)
   222  		err = helper.CreateOrderer(ibpCRClient, orderer.CR)
   223  		Expect(err).NotTo(HaveOccurred())
   224  	})
   225  
   226  	Eventually(org1peer.PodIsRunning).Should((Equal(true)))
   227  	Eventually(orderer.Nodes[0].PodIsRunning).Should((Equal(true)))
   228  }
   229  
   230  func downloadBinaries() {
   231  	os.Setenv("FABRIC_VERSION", FabricBinaryVersion)
   232  	os.Setenv("FABRIC_CA_VERSION", FabricCABinaryVersion)
   233  	sess, err := helper.StartSession(
   234  		helper.GetCommand(helper.AbsPath(wd, "../../scripts/download_binaries.sh")),
   235  		"Download Binaries",
   236  	)
   237  	Expect(err).NotTo(HaveOccurred())
   238  	Eventually(sess).Should(gexec.Exit(0))
   239  }
   240  
   241  func cleanupFiles() {
   242  	os.RemoveAll(filepath.Join(wd, Org1CA().Name))
   243  }
   244  
   245  func RestartOperator() {
   246  	fmt.Fprintf(GinkgoWriter, "Restarting operator\n")
   247  	integration.ShutdownOperator(GinkgoWriter)
   248  
   249  	fmt.Fprintf(GinkgoWriter, "Operator stopped\n")
   250  
   251  	// Currently triggering restart by closing channel results in following error on operator restart:
   252  	// {"level":"error","ts":1600966252.5380569,"logger":"controller-runtime.metrics","msg":"failed to register metric","name":"workqueue_retries_total","queue":"ibpconsole-controller","error":"duplicate metrics collector registration attempted"
   253  	//
   254  	// This error is not a breaking error, it can be ignored for testing purposes
   255  
   256  	fmt.Fprintf(GinkgoWriter, "Starting operator\n")
   257  	err := command.OperatorWithSignal(integration.OperatorCfg(), integration.SetupSignalHandler(), false, true)
   258  	Expect(err).NotTo(HaveOccurred())
   259  }
   260  
   261  func Org1CA() *helper.CA {
   262  	caOverrides := &v1.ServerConfig{
   263  		Debug: pointer.True(),
   264  		CAConfig: v1.CAConfig{
   265  			Affiliations: map[string]interface{}{
   266  				"org1": []string{"department1"},
   267  			},
   268  			DB: &v1.CAConfigDB{
   269  				Type: "sqlite3",
   270  			},
   271  		},
   272  	}
   273  	caJson, err := util.ConvertToJsonMessage(caOverrides)
   274  	Expect(err).NotTo(HaveOccurred())
   275  
   276  	name := "ibpca1"
   277  	cr := &current.IBPCA{
   278  		ObjectMeta: metav1.ObjectMeta{
   279  			Name:      name,
   280  			Namespace: namespace,
   281  		},
   282  		Spec: current.IBPCASpec{
   283  			License: current.License{
   284  				Accept: true,
   285  			},
   286  			ImagePullSecrets: []string{"regcred"},
   287  			Domain:           domain,
   288  			Images: &current.CAImages{
   289  				CAImage:     integration.CaImage,
   290  				CATag:       integration.CaTag,
   291  				CAInitImage: integration.InitImage,
   292  				CAInitTag:   integration.InitTag,
   293  			},
   294  			ConfigOverride: &current.ConfigOverride{
   295  				CA:    &runtime.RawExtension{Raw: *caJson},
   296  				TLSCA: &runtime.RawExtension{Raw: *caJson},
   297  			},
   298  			FabricVersion: integration.FabricCAVersion,
   299  		},
   300  	}
   301  
   302  	return &helper.CA{
   303  		Domain:     domain,
   304  		Name:       cr.Name,
   305  		Namespace:  namespace,
   306  		WorkingDir: wd,
   307  		CR:         cr,
   308  		CRClient:   ibpCRClient,
   309  		KClient:    kclient,
   310  		NativeResourcePoller: integration.NativeResourcePoller{
   311  			Name:      cr.Name,
   312  			Namespace: namespace,
   313  			Client:    kclient,
   314  		},
   315  	}
   316  }
   317  
   318  func Org1Peer(tlsCert, caHost, adminCert string) *helper.Peer {
   319  	cr, err := helper.Org1PeerCR(namespace, domain, peerUsername, tlsCert, caHost, adminCert)
   320  	Expect(err).NotTo(HaveOccurred())
   321  
   322  	return &helper.Peer{
   323  		Domain:     domain,
   324  		Name:       cr.Name,
   325  		Namespace:  namespace,
   326  		WorkingDir: wd,
   327  		CR:         cr,
   328  		CRClient:   ibpCRClient,
   329  		KClient:    kclient,
   330  		NativeResourcePoller: integration.NativeResourcePoller{
   331  			Name:      cr.Name,
   332  			Namespace: namespace,
   333  			Client:    kclient,
   334  		},
   335  	}
   336  }
   337  
   338  func GetOrderer(tlsCert, caHost string) *helper.Orderer {
   339  	cr, err := helper.OrdererCR(namespace, domain, ordererUsername, tlsCert, caHost)
   340  	Expect(err).NotTo(HaveOccurred())
   341  
   342  	nodes := []helper.Orderer{
   343  		helper.Orderer{
   344  			Name:      cr.Name + "node1",
   345  			Namespace: namespace,
   346  			CR:        cr.DeepCopy(),
   347  			NodeName:  fmt.Sprintf("%s%s%d", cr.Name, baseorderer.NODE, 1),
   348  			NativeResourcePoller: integration.NativeResourcePoller{
   349  				Name:      cr.Name + "node1",
   350  				Namespace: namespace,
   351  				Client:    kclient,
   352  			},
   353  		},
   354  	}
   355  
   356  	nodes[0].CR.ObjectMeta.Name = cr.Name + "node1"
   357  
   358  	return &helper.Orderer{
   359  		Name:      cr.Name,
   360  		Namespace: namespace,
   361  		CR:        cr,
   362  		NodeName:  fmt.Sprintf("%s-%s%d", cr.Name, baseorderer.NODE, 1),
   363  		NativeResourcePoller: integration.NativeResourcePoller{
   364  			Name:      cr.Name,
   365  			Namespace: namespace,
   366  			Client:    kclient,
   367  		},
   368  		Nodes: nodes,
   369  	}
   370  }