sigs.k8s.io/cluster-api@v1.7.1/cmd/clusterctl/client/move_test.go (about)

     1  /*
     2  Copyright 2020 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package client
    18  
    19  import (
    20  	"context"
    21  	"os"
    22  	"testing"
    23  
    24  	. "github.com/onsi/gomega"
    25  
    26  	clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3"
    27  	"sigs.k8s.io/cluster-api/cmd/clusterctl/client/cluster"
    28  	"sigs.k8s.io/cluster-api/cmd/clusterctl/client/config"
    29  	"sigs.k8s.io/cluster-api/cmd/clusterctl/internal/test"
    30  )
    31  
    32  func Test_clusterctlClient_Move(t *testing.T) {
    33  	type fields struct {
    34  		client *fakeClient
    35  	}
    36  	type args struct {
    37  		options MoveOptions
    38  	}
    39  	tests := []struct {
    40  		name    string
    41  		fields  fields
    42  		args    args
    43  		wantErr bool
    44  	}{
    45  		{
    46  			name: "does not return error if cluster client is found",
    47  			fields: fields{
    48  				client: fakeClientForMove(), // core v1.0.0 (v1.0.1 available), infra v2.0.0 (v2.0.1 available)
    49  			},
    50  			args: args{
    51  				options: MoveOptions{
    52  					FromKubeconfig: Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
    53  					ToKubeconfig:   Kubeconfig{Path: "kubeconfig", Context: "worker-context"},
    54  				},
    55  			},
    56  			wantErr: false,
    57  		},
    58  		{
    59  			name: "returns an error if from cluster client is not found",
    60  			fields: fields{
    61  				client: fakeClientForMove(), // core v1.0.0 (v1.0.1 available), infra v2.0.0 (v2.0.1 available)
    62  			},
    63  			args: args{
    64  				options: MoveOptions{
    65  					FromKubeconfig: Kubeconfig{Path: "kubeconfig", Context: "does-not-exist"},
    66  					ToKubeconfig:   Kubeconfig{Path: "kubeconfig", Context: "worker-context"},
    67  				},
    68  			},
    69  			wantErr: true,
    70  		},
    71  		{
    72  			name: "returns an error if to cluster client is not found",
    73  			fields: fields{
    74  				client: fakeClientForMove(), // core v1.0.0 (v1.0.1 available), infra v2.0.0 (v2.0.1 available)
    75  			},
    76  			args: args{
    77  				options: MoveOptions{
    78  					FromKubeconfig: Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
    79  					ToKubeconfig:   Kubeconfig{Path: "kubeconfig", Context: "does-not-exist"},
    80  				},
    81  			},
    82  			wantErr: true,
    83  		},
    84  		{
    85  			name: "returns an error if both move ToDirectory and FromDirectory is set",
    86  			fields: fields{
    87  				client: fakeClientForMove(),
    88  			},
    89  			args: args{
    90  				options: MoveOptions{
    91  					ToDirectory:   "/var/cache/toDirectory",
    92  					FromDirectory: "/var/cache/fromDirectory",
    93  				},
    94  			},
    95  			wantErr: true,
    96  		},
    97  		{
    98  			name: "returns an error if neither FromDirectory, ToDirectory, or ToKubeconfig is set",
    99  			fields: fields{
   100  				client: fakeClientForMove(),
   101  			},
   102  			args: args{
   103  				options: MoveOptions{
   104  					FromKubeconfig: Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
   105  					FromDirectory:  "",
   106  					ToDirectory:    "",
   107  					ToKubeconfig:   Kubeconfig{},
   108  				},
   109  			},
   110  			wantErr: true,
   111  		},
   112  		{
   113  			name: "does not return an error if dryRun but neither FromDirectory, ToDirectory, or ToKubeconfig is set",
   114  			fields: fields{
   115  				client: fakeClientForMove(),
   116  			},
   117  			args: args{
   118  				options: MoveOptions{
   119  					FromKubeconfig: Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
   120  					FromDirectory:  "",
   121  					ToKubeconfig:   Kubeconfig{},
   122  					DryRun:         true,
   123  				},
   124  			},
   125  			wantErr: false,
   126  		},
   127  	}
   128  
   129  	for _, tt := range tests {
   130  		t.Run(tt.name, func(t *testing.T) {
   131  			g := NewWithT(t)
   132  
   133  			ctx := context.Background()
   134  
   135  			err := tt.fields.client.Move(ctx, tt.args.options)
   136  			if tt.wantErr {
   137  				g.Expect(err).To(HaveOccurred())
   138  				return
   139  			}
   140  			g.Expect(err).ToNot(HaveOccurred())
   141  		})
   142  	}
   143  }
   144  
   145  func Test_clusterctlClient_ToDirectory(t *testing.T) {
   146  	dir, err := os.MkdirTemp("/tmp", "cluster-api")
   147  	if err != nil {
   148  		t.Error(err)
   149  	}
   150  	defer os.RemoveAll(dir)
   151  
   152  	type fields struct {
   153  		client *fakeClient
   154  	}
   155  	// These tests are checking the Backup scaffolding
   156  	// The internal library handles the backup logic and tests can be found there
   157  	type args struct {
   158  		options MoveOptions
   159  	}
   160  	tests := []struct {
   161  		name    string
   162  		fields  fields
   163  		args    args
   164  		wantErr bool
   165  	}{
   166  		{
   167  			name: "does not return error if cluster client is found",
   168  			fields: fields{
   169  				client: fakeClientForMove(), // core v1.0.0 (v1.0.1 available), infra v2.0.0 (v2.0.1 available)
   170  			},
   171  			args: args{
   172  				options: MoveOptions{
   173  					FromKubeconfig: Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
   174  					ToDirectory:    dir,
   175  				},
   176  			},
   177  			wantErr: false,
   178  		},
   179  		{
   180  			name: "returns an error if from cluster client is not found",
   181  			fields: fields{
   182  				client: fakeClientForMove(), // core v1.0.0 (v1.0.1 available), infra v2.0.0 (v2.0.1 available)
   183  			},
   184  			args: args{
   185  				options: MoveOptions{
   186  					FromKubeconfig: Kubeconfig{Path: "kubeconfig", Context: "does-not-exist"},
   187  					ToDirectory:    dir,
   188  				},
   189  			},
   190  			wantErr: true,
   191  		},
   192  	}
   193  
   194  	for _, tt := range tests {
   195  		t.Run(tt.name, func(t *testing.T) {
   196  			g := NewWithT(t)
   197  
   198  			ctx := context.Background()
   199  
   200  			err := tt.fields.client.Move(ctx, tt.args.options)
   201  			if tt.wantErr {
   202  				g.Expect(err).To(HaveOccurred())
   203  				return
   204  			}
   205  			g.Expect(err).ToNot(HaveOccurred())
   206  		})
   207  	}
   208  }
   209  
   210  func Test_clusterctlClient_FromDirectory(t *testing.T) {
   211  	dir, err := os.MkdirTemp("/tmp", "cluster-api")
   212  	if err != nil {
   213  		t.Error(err)
   214  	}
   215  	defer os.RemoveAll(dir)
   216  
   217  	type fields struct {
   218  		client *fakeClient
   219  	}
   220  	// These tests are checking the Restore scaffolding
   221  	// The internal library handles the restore logic and tests can be found there
   222  	type args struct {
   223  		options MoveOptions
   224  	}
   225  	tests := []struct {
   226  		name    string
   227  		fields  fields
   228  		args    args
   229  		wantErr bool
   230  	}{
   231  		{
   232  			name: "does not return error if cluster client is found",
   233  			fields: fields{
   234  				client: fakeClientForMove(), // core v1.0.0 (v1.0.1 available), infra v2.0.0 (v2.0.1 available)
   235  			},
   236  			args: args{
   237  				options: MoveOptions{
   238  					ToKubeconfig:  Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
   239  					FromDirectory: dir,
   240  				},
   241  			},
   242  			wantErr: false,
   243  		},
   244  		{
   245  			name: "returns an error if to cluster client is not found",
   246  			fields: fields{
   247  				client: fakeClientForMove(), // core v1.0.0 (v1.0.1 available), infra v2.0.0 (v2.0.1 available)
   248  			},
   249  			args: args{
   250  				options: MoveOptions{
   251  					ToKubeconfig:  Kubeconfig{Path: "kubeconfig", Context: "does-not-exist"},
   252  					FromDirectory: dir,
   253  				},
   254  			},
   255  			wantErr: true,
   256  		},
   257  	}
   258  
   259  	for _, tt := range tests {
   260  		t.Run(tt.name, func(t *testing.T) {
   261  			g := NewWithT(t)
   262  
   263  			ctx := context.Background()
   264  
   265  			err := tt.fields.client.Move(ctx, tt.args.options)
   266  			if tt.wantErr {
   267  				g.Expect(err).To(HaveOccurred())
   268  				return
   269  			}
   270  			g.Expect(err).ToNot(HaveOccurred())
   271  		})
   272  	}
   273  }
   274  
   275  func fakeClientForMove() *fakeClient {
   276  	ctx := context.Background()
   277  
   278  	core := config.NewProvider("cluster-api", "https://somewhere.com", clusterctlv1.CoreProviderType)
   279  	infra := config.NewProvider("infra", "https://somewhere.com", clusterctlv1.InfrastructureProviderType)
   280  
   281  	config1 := newFakeConfig(ctx).
   282  		WithProvider(core).
   283  		WithProvider(infra)
   284  
   285  	cluster1 := newFakeCluster(cluster.Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"}, config1).
   286  		WithProviderInventory(core.Name(), core.Type(), "v1.0.0", "cluster-api-system").
   287  		WithProviderInventory(infra.Name(), infra.Type(), "v2.0.0", "infra-system").
   288  		WithObjectMover(&fakeObjectMover{}).
   289  		WithObjs(test.FakeCAPISetupObjects()...)
   290  
   291  	// Creating this cluster for move_test
   292  	cluster2 := newFakeCluster(cluster.Kubeconfig{Path: "kubeconfig", Context: "worker-context"}, config1).
   293  		WithProviderInventory(core.Name(), core.Type(), "v1.0.0", "cluster-api-system").
   294  		WithProviderInventory(infra.Name(), infra.Type(), "v2.0.0", "infra-system").
   295  		WithObjs(test.FakeCAPISetupObjects()...)
   296  
   297  	client := newFakeClient(ctx, config1).
   298  		WithCluster(cluster1).
   299  		WithCluster(cluster2)
   300  
   301  	return client
   302  }
   303  
   304  type fakeObjectMover struct {
   305  	moveErr          error
   306  	toDirectoryErr   error
   307  	fromDirectoryErr error
   308  }
   309  
   310  func (f *fakeObjectMover) Move(_ context.Context, _ string, _ cluster.Client, _ bool, _ ...cluster.ResourceMutatorFunc) error {
   311  	return f.moveErr
   312  }
   313  
   314  func (f *fakeObjectMover) ToDirectory(_ context.Context, _ string, _ string) error {
   315  	return f.toDirectoryErr
   316  }
   317  
   318  func (f *fakeObjectMover) Backup(_ context.Context, _ string, _ string) error {
   319  	return f.toDirectoryErr
   320  }
   321  
   322  func (f *fakeObjectMover) FromDirectory(_ context.Context, _ cluster.Client, _ string) error {
   323  	return f.fromDirectoryErr
   324  }
   325  
   326  func (f *fakeObjectMover) Restore(_ context.Context, _ cluster.Client, _ string) error {
   327  	return f.fromDirectoryErr
   328  }