github.com/IBM-Blockchain/fabric-operator@v1.0.4/integration/actions/peer/peer_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 peer_test
    20  
    21  import (
    22  	"bytes"
    23  	"context"
    24  	"encoding/base64"
    25  	"encoding/json"
    26  	"fmt"
    27  
    28  	. "github.com/onsi/ginkgo/v2"
    29  	. "github.com/onsi/gomega"
    30  	"sigs.k8s.io/controller-runtime/pkg/client"
    31  
    32  	current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1"
    33  	"github.com/IBM-Blockchain/fabric-operator/integration"
    34  	"github.com/IBM-Blockchain/fabric-operator/integration/helper"
    35  	"github.com/IBM-Blockchain/fabric-operator/pkg/offering/common"
    36  
    37  	k8serrors "k8s.io/apimachinery/pkg/api/errors"
    38  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    39  )
    40  
    41  var _ = Describe("trigger peer actions", func() {
    42  	AfterEach(func() {
    43  		// Set flag if a test falls
    44  		if CurrentGinkgoTestDescription().Failed {
    45  			testFailed = true
    46  		}
    47  	})
    48  
    49  	var (
    50  		podName string
    51  		ibppeer *current.IBPPeer
    52  	)
    53  
    54  	BeforeEach(func() {
    55  		Eventually(func() int { return len(org1peer.GetRunningPods()) }).Should(Equal(1))
    56  		podName = org1peer.GetRunningPods()[0].Name
    57  
    58  		integration.ClearOperatorConfig(kclient, namespace)
    59  	})
    60  
    61  	When("spec has restart flag set to true", func() {
    62  		It("performs restart action", func() {
    63  			patch := func(o client.Object) {
    64  				ibppeer = o.(*current.IBPPeer)
    65  				ibppeer.Spec.Action.Restart = true
    66  			}
    67  
    68  			err := integration.ResilientPatch(ibpCRClient, org1peer.Name, namespace, IBPPEERS, 3, &current.IBPPeer{}, patch)
    69  			Expect(err).NotTo(HaveOccurred())
    70  
    71  			Eventually(org1peer.PodIsRunning).Should((Equal(true)))
    72  
    73  			By("restarting peer pods", func() {
    74  				Eventually(func() bool {
    75  					pods := org1peer.GetRunningPods()
    76  					if len(pods) == 0 {
    77  						return false
    78  					}
    79  
    80  					newPodName := pods[0].Name
    81  					if newPodName != podName {
    82  						return true
    83  					}
    84  
    85  					return false
    86  				}).Should(Equal(true))
    87  			})
    88  
    89  			By("setting restart flag back to false after restart", func() {
    90  				Eventually(func() bool {
    91  					result := ibpCRClient.Get().Namespace(namespace).Resource(IBPPEERS).Name(org1peer.Name).Do(context.TODO())
    92  					ibppeer := &current.IBPPeer{}
    93  					result.Into(ibppeer)
    94  
    95  					return ibppeer.Spec.Action.Restart
    96  				}).Should(Equal(false))
    97  			})
    98  		})
    99  	})
   100  
   101  	When("spec has ecert reenroll flag set to true", func() {
   102  		var (
   103  			ecert, ekey []byte
   104  
   105  			commonAssertions = func() {
   106  				By("restarting peer pods", func() {
   107  					Eventually(func() bool {
   108  						pods := org1peer.GetRunningPods()
   109  						if len(pods) == 0 {
   110  							return false
   111  						}
   112  
   113  						newPodName := pods[0].Name
   114  						if newPodName != podName {
   115  							return true
   116  						}
   117  
   118  						return false
   119  					}).Should(Equal(true))
   120  				})
   121  
   122  				By("backing up old signcert", func() {
   123  					backup := GetBackup("ecert", org1peer.Name)
   124  					Expect(len(backup.List)).NotTo(Equal(0))
   125  					Expect(backup.List[len(backup.List)-1].SignCerts).To(Equal(base64.StdEncoding.EncodeToString(ecert)))
   126  				})
   127  
   128  				By("updating ecert signcert secret", func() {
   129  					updatedEcertSecret, err := kclient.CoreV1().Secrets(namespace).Get(context.TODO(), fmt.Sprintf("ecert-%s-signcert", org1peer.Name), metav1.GetOptions{})
   130  					Expect(err).NotTo(HaveOccurred())
   131  
   132  					Expect(bytes.Equal(ecert, updatedEcertSecret.Data["cert.pem"])).To(Equal(false))
   133  				})
   134  			}
   135  		)
   136  
   137  		BeforeEach(func() {
   138  			ecertSecret, err := kclient.CoreV1().Secrets(namespace).
   139  				Get(context.TODO(), fmt.Sprintf("ecert-%s-signcert", org1peer.Name), metav1.GetOptions{})
   140  			Expect(err).NotTo(HaveOccurred())
   141  			ecert = ecertSecret.Data["cert.pem"]
   142  
   143  			ecertSecret, err = kclient.CoreV1().Secrets(namespace).
   144  				Get(context.TODO(), fmt.Sprintf("ecert-%s-keystore", org1peer.Name), metav1.GetOptions{})
   145  			Expect(err).NotTo(HaveOccurred())
   146  			ekey = ecertSecret.Data["key.pem"]
   147  		})
   148  
   149  		It("gets a new certificate and key", func() {
   150  			patch := func(o client.Object) {
   151  				ibppeer = o.(*current.IBPPeer)
   152  				ibppeer.Spec.Action.Reenroll.EcertNewKey = true
   153  			}
   154  
   155  			err := integration.ResilientPatch(
   156  				ibpCRClient,
   157  				org1peer.Name,
   158  				namespace,
   159  				IBPPEERS,
   160  				3,
   161  				&current.IBPPeer{},
   162  				patch)
   163  			Expect(err).NotTo(HaveOccurred())
   164  
   165  			commonAssertions()
   166  
   167  			By("generating a new key", func() {
   168  				updatedEcertKey, err := kclient.CoreV1().Secrets(namespace).
   169  					Get(context.TODO(), fmt.Sprintf("ecert-%s-keystore", org1peer.Name), metav1.GetOptions{})
   170  				Expect(err).NotTo(HaveOccurred())
   171  				Expect(bytes.Equal(ekey, updatedEcertKey.Data["key.pem"])).To(Equal(false))
   172  			})
   173  
   174  			By("setting reenroll flag back to false after restart", func() {
   175  				ibppeer := &current.IBPPeer{}
   176  				Eventually(func() bool {
   177  					result := ibpCRClient.Get().Namespace(namespace).Resource(IBPPEERS).Name(org1peer.Name).Do(context.TODO())
   178  					result.Into(ibppeer)
   179  
   180  					return ibppeer.Spec.Action.Reenroll.EcertNewKey
   181  				}).Should(Equal(false))
   182  			})
   183  		})
   184  
   185  		It("gets a new certificate", func() {
   186  			patch := func(o client.Object) {
   187  				ibppeer = o.(*current.IBPPeer)
   188  				ibppeer.Spec.Action.Reenroll.Ecert = true
   189  			}
   190  
   191  			err := integration.ResilientPatch(
   192  				ibpCRClient,
   193  				org1peer.Name,
   194  				namespace,
   195  				IBPPEERS,
   196  				3,
   197  				&current.IBPPeer{},
   198  				patch)
   199  			Expect(err).NotTo(HaveOccurred())
   200  
   201  			commonAssertions()
   202  
   203  			By("not generating a new key", func() {
   204  				updatedEcertKey, err := kclient.CoreV1().Secrets(namespace).
   205  					Get(context.TODO(), fmt.Sprintf("ecert-%s-keystore", org1peer.Name), metav1.GetOptions{})
   206  				Expect(err).NotTo(HaveOccurred())
   207  				Expect(bytes.Equal(ekey, updatedEcertKey.Data["key.pem"])).To(Equal(true))
   208  			})
   209  
   210  			By("setting reenroll flag back to false after restart", func() {
   211  				ibppeer := &current.IBPPeer{}
   212  				Eventually(func() bool {
   213  					result := ibpCRClient.Get().Namespace(namespace).Resource(IBPPEERS).Name(org1peer.Name).Do(context.TODO())
   214  					result.Into(ibppeer)
   215  
   216  					return ibppeer.Spec.Action.Reenroll.Ecert
   217  				}).Should(Equal(false))
   218  			})
   219  		})
   220  	})
   221  
   222  	When("spec has TLS reenroll flag set to true", func() {
   223  		var (
   224  			cert, key []byte
   225  
   226  			commonAssertions = func() {
   227  				By("restarting peer pods", func() {
   228  					Eventually(func() bool {
   229  						pods := org1peer.GetRunningPods()
   230  						if len(pods) == 0 {
   231  							return false
   232  						}
   233  
   234  						newPodName := pods[0].Name
   235  						if newPodName != podName {
   236  							return true
   237  						}
   238  
   239  						return false
   240  					}).Should(Equal(true))
   241  				})
   242  
   243  				By("backing up old signcert", func() {
   244  					backup := GetBackup("tls", org1peer.Name)
   245  					Expect(len(backup.List)).NotTo(Equal(0))
   246  					Expect(backup.List[len(backup.List)-1].SignCerts).To(Equal(base64.StdEncoding.EncodeToString(cert)))
   247  				})
   248  
   249  				By("updating tls signcert secret", func() {
   250  					updatedTLSSecret, err := kclient.CoreV1().Secrets(namespace).Get(context.TODO(), fmt.Sprintf("tls-%s-signcert", org1peer.Name), metav1.GetOptions{})
   251  					Expect(err).NotTo(HaveOccurred())
   252  
   253  					Expect(bytes.Equal(cert, updatedTLSSecret.Data["cert.pem"])).To(Equal(false))
   254  				})
   255  			}
   256  		)
   257  
   258  		BeforeEach(func() {
   259  			tlsSecret, err := kclient.CoreV1().Secrets(namespace).
   260  				Get(context.TODO(), fmt.Sprintf("tls-%s-signcert", org1peer.Name), metav1.GetOptions{})
   261  			Expect(err).NotTo(HaveOccurred())
   262  			cert = tlsSecret.Data["cert.pem"]
   263  
   264  			tlsSecret, err = kclient.CoreV1().Secrets(namespace).
   265  				Get(context.TODO(), fmt.Sprintf("tls-%s-keystore", org1peer.Name), metav1.GetOptions{})
   266  			Expect(err).NotTo(HaveOccurred())
   267  			key = tlsSecret.Data["key.pem"]
   268  		})
   269  
   270  		When("requesting a new key", func() {
   271  			It("gets a new key and certificate", func() {
   272  				patch := func(o client.Object) {
   273  					ibppeer = o.(*current.IBPPeer)
   274  					ibppeer.Spec.Action.Reenroll.TLSCertNewKey = true
   275  				}
   276  
   277  				err := integration.ResilientPatch(
   278  					ibpCRClient,
   279  					org1peer.Name,
   280  					namespace,
   281  					IBPPEERS,
   282  					3,
   283  					&current.IBPPeer{},
   284  					patch)
   285  				Expect(err).NotTo(HaveOccurred())
   286  
   287  				commonAssertions()
   288  
   289  				By("generating a new key", func() {
   290  					updatedKey, err := kclient.CoreV1().Secrets(namespace).
   291  						Get(context.TODO(), fmt.Sprintf("tls-%s-keystore", org1peer.Name), metav1.GetOptions{})
   292  					Expect(err).NotTo(HaveOccurred())
   293  
   294  					Expect(bytes.Equal(key, updatedKey.Data["key.pem"])).To(Equal(false))
   295  				})
   296  
   297  				By("setting reenroll flag back to false after restart", func() {
   298  					Eventually(func() bool {
   299  						result := ibpCRClient.Get().Namespace(namespace).Resource(IBPPEERS).Name(org1peer.Name).Do(context.TODO())
   300  						ibppeer := &current.IBPPeer{}
   301  						result.Into(ibppeer)
   302  
   303  						return ibppeer.Spec.Action.Reenroll.TLSCertNewKey
   304  					}).Should(Equal(false))
   305  				})
   306  			})
   307  		})
   308  
   309  		When("reusing existing key", func() {
   310  			It("gets a new certificate", func() {
   311  				patch := func(o client.Object) {
   312  					ibppeer = o.(*current.IBPPeer)
   313  					ibppeer.Spec.Action.Reenroll.TLSCert = true
   314  				}
   315  
   316  				err := integration.ResilientPatch(
   317  					ibpCRClient,
   318  					org1peer.Name,
   319  					namespace,
   320  					IBPPEERS,
   321  					3,
   322  					&current.IBPPeer{},
   323  					patch)
   324  				Expect(err).NotTo(HaveOccurred())
   325  
   326  				commonAssertions()
   327  
   328  				By("not generating a new key", func() {
   329  					updatedKey, err := kclient.CoreV1().Secrets(namespace).
   330  						Get(context.TODO(), fmt.Sprintf("tls-%s-keystore", org1peer.Name), metav1.GetOptions{})
   331  					Expect(err).NotTo(HaveOccurred())
   332  					Expect(bytes.Equal(key, updatedKey.Data["key.pem"])).To(Equal(true))
   333  				})
   334  
   335  				By("setting reenroll flag back to false after restart", func() {
   336  					Eventually(func() bool {
   337  						result := ibpCRClient.Get().Namespace(namespace).Resource(IBPPEERS).Name(org1peer.Name).Do(context.TODO())
   338  						ibppeer := &current.IBPPeer{}
   339  						result.Into(ibppeer)
   340  
   341  						return ibppeer.Spec.Action.Reenroll.TLSCert
   342  					}).Should(Equal(false))
   343  				})
   344  			})
   345  		})
   346  	})
   347  
   348  	When("spec has ecert enroll flag set to true", func() {
   349  		var (
   350  			ecert    []byte
   351  			ecertKey []byte
   352  		)
   353  
   354  		BeforeEach(func() {
   355  			ecertSecret, err := kclient.CoreV1().
   356  				Secrets(namespace).
   357  				Get(context.TODO(), fmt.Sprintf("ecert-%s-signcert", org1peer.Name), metav1.GetOptions{})
   358  			Expect(err).NotTo(HaveOccurred())
   359  
   360  			ecertKeySecret, err := kclient.CoreV1().
   361  				Secrets(namespace).
   362  				Get(context.TODO(), fmt.Sprintf("ecert-%s-keystore", org1peer.Name), metav1.GetOptions{})
   363  			Expect(err).NotTo(HaveOccurred())
   364  
   365  			ecert = ecertSecret.Data["cert.pem"]
   366  			ecertKey = ecertKeySecret.Data["key.pem"]
   367  		})
   368  
   369  		It("generates new crypto", func() {
   370  			patch := func(o client.Object) {
   371  				ibppeer = o.(*current.IBPPeer)
   372  				ibppeer.Spec.Action.Enroll.Ecert = true
   373  			}
   374  
   375  			err := integration.ResilientPatch(ibpCRClient, org1peer.Name, namespace, IBPPEERS, 3, &current.IBPPeer{}, patch)
   376  			Expect(err).NotTo(HaveOccurred())
   377  
   378  			By("backing up old crypto", func() {
   379  				Eventually(func() bool {
   380  					backup := GetBackup("ecert", org1peer.Name)
   381  					if len(backup.List) == 0 {
   382  						return false
   383  					}
   384  
   385  					return backup.List[len(backup.List)-1].SignCerts == base64.StdEncoding.EncodeToString(ecert) &&
   386  						backup.List[len(backup.List)-1].KeyStore == base64.StdEncoding.EncodeToString(ecertKey)
   387  				}).Should(Equal(true))
   388  			})
   389  
   390  			By("updating ecert signcert secret", func() {
   391  				Eventually(func() bool {
   392  					updatedEcertSecret, err := kclient.CoreV1().
   393  						Secrets(namespace).
   394  						Get(context.TODO(), fmt.Sprintf("ecert-%s-signcert", org1peer.Name), metav1.GetOptions{})
   395  					Expect(err).NotTo(HaveOccurred())
   396  
   397  					return bytes.Equal(ecert, updatedEcertSecret.Data["cert.pem"])
   398  				}).Should(Equal(false))
   399  			})
   400  
   401  			By("updating ecert key secret", func() {
   402  				Eventually(func() bool {
   403  					updatedEcertSecret, err := kclient.CoreV1().
   404  						Secrets(namespace).
   405  						Get(context.TODO(), fmt.Sprintf("ecert-%s-keystore", org1peer.Name), metav1.GetOptions{})
   406  					Expect(err).NotTo(HaveOccurred())
   407  
   408  					return bytes.Equal(ecertKey, updatedEcertSecret.Data["key.pem"])
   409  				}).Should(Equal(false))
   410  			})
   411  
   412  			By("setting ecert action flag back to false in spec after completion", func() {
   413  				Eventually(func() bool {
   414  					result := ibpCRClient.Get().Namespace(namespace).
   415  						Resource(IBPPEERS).
   416  						Name(org1peer.Name).
   417  						Do(context.TODO())
   418  					ibppeer := &current.IBPPeer{}
   419  					result.Into(ibppeer)
   420  
   421  					return ibppeer.Spec.Action.Enroll.Ecert
   422  				}).Should(Equal(false))
   423  			})
   424  		})
   425  	})
   426  
   427  	When("spec has tls enroll flag set to true", func() {
   428  		var (
   429  			tlscert []byte
   430  			tlskey  []byte
   431  		)
   432  
   433  		BeforeEach(func() {
   434  			tlscertSecret, err := kclient.CoreV1().
   435  				Secrets(namespace).
   436  				Get(context.TODO(), fmt.Sprintf("tls-%s-signcert", org1peer.Name), metav1.GetOptions{})
   437  			Expect(err).NotTo(HaveOccurred())
   438  
   439  			tlskeySecret, err := kclient.CoreV1().
   440  				Secrets(namespace).
   441  				Get(context.TODO(), fmt.Sprintf("tls-%s-keystore", org1peer.Name), metav1.GetOptions{})
   442  			Expect(err).NotTo(HaveOccurred())
   443  
   444  			tlscert = tlscertSecret.Data["cert.pem"]
   445  			tlskey = tlskeySecret.Data["key.pem"]
   446  		})
   447  
   448  		It("generates new crypto", func() {
   449  			patch := func(o client.Object) {
   450  				ibppeer = o.(*current.IBPPeer)
   451  				ibppeer.Spec.Action.Enroll.TLSCert = true
   452  			}
   453  
   454  			err := integration.ResilientPatch(ibpCRClient, org1peer.Name, namespace, IBPPEERS, 3, &current.IBPPeer{}, patch)
   455  			Expect(err).NotTo(HaveOccurred())
   456  
   457  			By("backing up old crypto", func() {
   458  				Eventually(func() bool {
   459  					backup := GetBackup("tls", org1peer.Name)
   460  					Expect(len(backup.List)).NotTo(Equal(0))
   461  					return backup.List[len(backup.List)-1].SignCerts == base64.StdEncoding.EncodeToString(tlscert) &&
   462  						backup.List[len(backup.List)-1].KeyStore == base64.StdEncoding.EncodeToString(tlskey)
   463  				}).Should(Equal(true))
   464  			})
   465  
   466  			By("updating ecert signcert secret", func() {
   467  				Eventually(func() bool {
   468  					updatedTlscertSecret, err := kclient.CoreV1().
   469  						Secrets(namespace).
   470  						Get(context.TODO(), fmt.Sprintf("tls-%s-signcert", org1peer.Name), metav1.GetOptions{})
   471  					Expect(err).NotTo(HaveOccurred())
   472  
   473  					return bytes.Equal(tlscert, updatedTlscertSecret.Data["cert.pem"])
   474  				}).Should(Equal(false))
   475  			})
   476  
   477  			By("updating ecert key secret", func() {
   478  				Eventually(func() bool {
   479  					updatedTlskeySecret, err := kclient.CoreV1().
   480  						Secrets(namespace).
   481  						Get(context.TODO(), fmt.Sprintf("tls-%s-keystore", org1peer.Name), metav1.GetOptions{})
   482  					Expect(err).NotTo(HaveOccurred())
   483  
   484  					return bytes.Equal(tlskey, updatedTlskeySecret.Data["key.pem"])
   485  				}).Should(Equal(false))
   486  			})
   487  
   488  			By("setting TLS action flag back to false in spec after completion", func() {
   489  				Eventually(func() bool {
   490  					result := ibpCRClient.Get().Namespace(namespace).
   491  						Resource(IBPPEERS).
   492  						Name(org1peer.Name).
   493  						Do(context.TODO())
   494  					ibppeer := &current.IBPPeer{}
   495  					result.Into(ibppeer)
   496  
   497  					return ibppeer.Spec.Action.Enroll.TLSCert
   498  				}).Should(Equal(false))
   499  			})
   500  		})
   501  	})
   502  
   503  	Context("upgrade dbs", func() {
   504  		var (
   505  			migrationJobName string
   506  			err              error
   507  		)
   508  
   509  		It("performs db reset job", func() {
   510  			patch := func(o client.Object) {
   511  				ibppeer = o.(*current.IBPPeer)
   512  				ibppeer.Spec.Action.UpgradeDBs = true
   513  			}
   514  
   515  			err = integration.ResilientPatch(ibpCRClient, org1peer.Name, namespace, IBPPEERS, 3, &current.IBPPeer{}, patch)
   516  			Expect(err).NotTo(HaveOccurred())
   517  
   518  			By("starting migration job", func() {
   519  				Eventually(func() bool {
   520  					migrationJobName, err = helper.GetJobID(kclient, namespace, fmt.Sprintf("%s-dbmigration", ibppeer.Name))
   521  					if err != nil {
   522  						return false
   523  					}
   524  
   525  					_, err = kclient.BatchV1().Jobs(namespace).
   526  						Get(context.TODO(), migrationJobName, metav1.GetOptions{})
   527  					if err != nil {
   528  						return false
   529  					}
   530  					return true
   531  				}).Should(Equal(true))
   532  			})
   533  
   534  			By("clearing out reset value after completion", func() {
   535  				Eventually(func() bool {
   536  					result := ibpCRClient.Get().Namespace(namespace).
   537  						Resource(IBPPEERS).
   538  						Name(org1peer.Name).
   539  						Do(context.TODO())
   540  
   541  					Expect(result.Error()).NotTo(HaveOccurred())
   542  
   543  					ibppeer = &current.IBPPeer{}
   544  					result.Into(ibppeer)
   545  
   546  					return ibppeer.Spec.Action.UpgradeDBs
   547  				}).Should(Equal(false))
   548  			})
   549  
   550  			By("removing migration job", func() {
   551  				Eventually(func() bool {
   552  					_, err := kclient.BatchV1().Jobs(namespace).
   553  						Get(context.TODO(), migrationJobName, metav1.GetOptions{})
   554  					if err != nil {
   555  						return true
   556  					}
   557  					return false
   558  				}).Should(Equal(true))
   559  			})
   560  
   561  			By("removing migration pod", func() {
   562  				Eventually(func() bool {
   563  					podList, err := kclient.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{
   564  						LabelSelector: fmt.Sprintf("job-name=%s-dbmigration", ibppeer.Name),
   565  					})
   566  					if err != nil {
   567  						return true
   568  					}
   569  
   570  					if len(podList.Items) == 0 {
   571  						return true
   572  					}
   573  
   574  					return false
   575  				}).Should(Equal(true))
   576  			})
   577  		})
   578  	})
   579  
   580  })
   581  
   582  func GetBackup(certType, name string) *common.Backup {
   583  	backupSecret, err := kclient.CoreV1().Secrets(namespace).Get(context.TODO(), fmt.Sprintf("%s-crypto-backup", name), metav1.GetOptions{})
   584  	if err != nil {
   585  		Expect(k8serrors.IsNotFound(err)).To(Equal(true))
   586  		return &common.Backup{}
   587  	}
   588  
   589  	backup := &common.Backup{}
   590  	key := fmt.Sprintf("%s-backup.json", certType)
   591  	err = json.Unmarshal(backupSecret.Data[key], backup)
   592  	Expect(err).NotTo(HaveOccurred())
   593  
   594  	return backup
   595  }