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