sigs.k8s.io/cluster-api@v1.6.3/cmd/clusterctl/client/repository/repository_gitlab_test.go (about)

     1  /*
     2  Copyright 2022 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 repository
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"net/http"
    23  	"net/http/httptest"
    24  	"testing"
    25  
    26  	. "github.com/onsi/gomega"
    27  
    28  	clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3"
    29  	"sigs.k8s.io/cluster-api/cmd/clusterctl/client/config"
    30  	"sigs.k8s.io/cluster-api/cmd/clusterctl/internal/test"
    31  )
    32  
    33  func Test_gitLabRepository_newGitLabRepository(t *testing.T) {
    34  	type field struct {
    35  		providerConfig config.Provider
    36  		variableClient config.VariablesClient
    37  	}
    38  	tests := []struct {
    39  		name      string
    40  		field     field
    41  		want      *gitLabRepository
    42  		wantedErr string
    43  	}{
    44  		{
    45  			name: "can create a new GitLab repo",
    46  			field: field{
    47  				providerConfig: config.NewProvider("test", "https://gitlab.example.org/api/v4/projects/group%2Fproject/packages/generic/my-package/v1.0/path", clusterctlv1.CoreProviderType),
    48  				variableClient: test.NewFakeVariableClient(),
    49  			},
    50  			want: &gitLabRepository{
    51  				providerConfig:        config.NewProvider("test", "https://gitlab.example.org/api/v4/projects/group%2Fproject/packages/generic/my-package/v1.0/path", clusterctlv1.CoreProviderType),
    52  				configVariablesClient: test.NewFakeVariableClient(),
    53  				httpClient:            http.DefaultClient,
    54  				host:                  "gitlab.example.org",
    55  				projectSlug:           "group%2Fproject",
    56  				packageName:           "my-package",
    57  				defaultVersion:        "v1.0",
    58  				rootPath:              ".",
    59  				componentsPath:        "path",
    60  			},
    61  			wantedErr: "",
    62  		},
    63  		{
    64  			name: "missing variableClient",
    65  			field: field{
    66  				providerConfig: config.NewProvider("test", "https://gitlab.example.org/api/v4/projects/group%2Fproject/packages/generic/my-package/v1.0/path", clusterctlv1.CoreProviderType),
    67  				variableClient: nil,
    68  			},
    69  			want:      nil,
    70  			wantedErr: "invalid arguments: configVariablesClient can't be nil",
    71  		},
    72  		{
    73  			name: "provider url is not valid",
    74  			field: field{
    75  				providerConfig: config.NewProvider("test", "%gh&%ij", clusterctlv1.CoreProviderType),
    76  				variableClient: test.NewFakeVariableClient(),
    77  			},
    78  			want:      nil,
    79  			wantedErr: "invalid url: parse \"%gh&%ij\": invalid URL escape \"%gh\"",
    80  		},
    81  		{
    82  			name: "provider url should be in https",
    83  			field: field{
    84  				providerConfig: config.NewProvider("test", "http://gitlab.example.org/api/v4/projects/group%2Fproject/packages/generic/my-package/v1.0/path", clusterctlv1.CoreProviderType),
    85  				variableClient: test.NewFakeVariableClient(),
    86  			},
    87  			want:      nil,
    88  			wantedErr: "invalid url: a GitLab repository url should be in the form https://{host}/api/v4/projects/{projectSlug}/packages/generic/{packageName}/{defaultVersion}/{componentsPath}",
    89  		},
    90  		{
    91  			name: "provider url should have the correct number of parts",
    92  			field: field{
    93  				providerConfig: config.NewProvider("test", "https://gitlab.example.org/api/v4/projects/group%2Fproject/packages/generic/my-package/v1.0/path/grrr", clusterctlv1.CoreProviderType),
    94  				variableClient: test.NewFakeVariableClient(),
    95  			},
    96  			want:      &gitLabRepository{},
    97  			wantedErr: "invalid url: a GitLab repository url should be in the form https://{host}/api/v4/projects/{projectSlug}/packages/generic/{packageName}/{defaultVersion}/{componentsPath}",
    98  		},
    99  		{
   100  			name: "provider url should have the correct prefix",
   101  			field: field{
   102  				providerConfig: config.NewProvider("test", "https://gitlab.example.org/subpath/api/v4/projects/group%2Fproject/packages/generic/my-package/v1.0/path", clusterctlv1.CoreProviderType),
   103  				variableClient: test.NewFakeVariableClient(),
   104  			},
   105  			want:      &gitLabRepository{},
   106  			wantedErr: "invalid url: a GitLab repository url should be in the form https://{host}/api/v4/projects/{projectSlug}/packages/generic/{packageName}/{defaultVersion}/{componentsPath}",
   107  		},
   108  		{
   109  			name: "provider url should have the packages part",
   110  			field: field{
   111  				providerConfig: config.NewProvider("test", "https://gitlab.example.org/api/v4/projects/group%2Fproject/packages-invalid/generic/my-package/v1.0/path", clusterctlv1.CoreProviderType),
   112  				variableClient: test.NewFakeVariableClient(),
   113  			},
   114  			want:      nil,
   115  			wantedErr: "invalid url: a GitLab repository url should be in the form https://{host}/api/v4/projects/{projectSlug}/packages/generic/{packageName}/{defaultVersion}/{componentsPath}",
   116  		},
   117  		{
   118  			name: "provider url should have the generic part",
   119  			field: field{
   120  				providerConfig: config.NewProvider("test", "https://gitlab.example.org/api/v4/projects/group%2Fproject/packages/generic-invalid/my-package/v1.0/path", clusterctlv1.CoreProviderType),
   121  				variableClient: test.NewFakeVariableClient(),
   122  			},
   123  			want:      nil,
   124  			wantedErr: "invalid url: a GitLab repository url should be in the form https://{host}/api/v4/projects/{projectSlug}/packages/generic/{packageName}/{defaultVersion}/{componentsPath}",
   125  		},
   126  	}
   127  
   128  	for _, tt := range tests {
   129  		t.Run(tt.name, func(t *testing.T) {
   130  			g := NewWithT(t)
   131  			resetCaches()
   132  
   133  			gitLab, err := NewGitLabRepository(tt.field.providerConfig, tt.field.variableClient)
   134  			if tt.wantedErr != "" {
   135  				g.Expect(err).To(MatchError(tt.wantedErr))
   136  				return
   137  			}
   138  
   139  			g.Expect(err).ToNot(HaveOccurred())
   140  			g.Expect(gitLab).To(Equal(tt.want))
   141  		})
   142  	}
   143  }
   144  
   145  func Test_gitLabRepository_getFile(t *testing.T) {
   146  	mux := http.NewServeMux()
   147  	server := httptest.NewTLSServer(mux)
   148  	defer server.Close()
   149  	client := server.Client()
   150  
   151  	providerURL := fmt.Sprintf("%s/api/v4/projects/group%%2Fproject/packages/generic/my-package/v0.4.1/file.yaml", server.URL)
   152  	providerConfig := config.NewProvider("test", providerURL, clusterctlv1.CoreProviderType)
   153  
   154  	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
   155  		testMethod(t, r, "GET")
   156  		if r.URL.RawPath == "/api/v4/projects/group%2Fproject/packages/generic/my-package/v0.4.1/file.yaml" {
   157  			w.Header().Set("Content-Type", "application/octet-stream")
   158  			w.Header().Set("Content-Disposition", "attachment; filename=file.yaml")
   159  			fmt.Fprint(w, "content")
   160  			return
   161  		}
   162  		http.NotFound(w, r)
   163  	})
   164  
   165  	configVariablesClient := test.NewFakeVariableClient()
   166  
   167  	tests := []struct {
   168  		name     string
   169  		version  string
   170  		fileName string
   171  		want     []byte
   172  		wantErr  bool
   173  	}{
   174  		{
   175  			name:     "Release and file exist",
   176  			version:  "v0.4.1",
   177  			fileName: "file.yaml",
   178  			want:     []byte("content"),
   179  			wantErr:  false,
   180  		},
   181  		{
   182  			name:     "File does not exist",
   183  			version:  "v0.4.1",
   184  			fileName: "404.file",
   185  			want:     nil,
   186  			wantErr:  true,
   187  		},
   188  	}
   189  
   190  	for _, tt := range tests {
   191  		t.Run(tt.name, func(t *testing.T) {
   192  			g := NewWithT(t)
   193  			resetCaches()
   194  
   195  			gitLab, err := NewGitLabRepository(providerConfig, configVariablesClient)
   196  			gitLab.(*gitLabRepository).httpClient = client
   197  			g.Expect(err).ToNot(HaveOccurred())
   198  
   199  			got, err := gitLab.GetFile(context.Background(), tt.version, tt.fileName)
   200  			if tt.wantErr {
   201  				g.Expect(err).To(HaveOccurred())
   202  				return
   203  			}
   204  
   205  			g.Expect(err).ToNot(HaveOccurred())
   206  			g.Expect(got).To(Equal(tt.want))
   207  		})
   208  	}
   209  }