github.com/replicatedcom/ship@v0.50.0/pkg/specs/githubclient/client_test.go (about) 1 package githubclient 2 3 import ( 4 "context" 5 "encoding/base64" 6 "io" 7 "net/http" 8 "net/http/httptest" 9 "net/url" 10 "path" 11 "path/filepath" 12 "strings" 13 "testing" 14 15 "github.com/go-kit/kit/log" 16 "github.com/google/go-github/github" 17 . "github.com/onsi/ginkgo" 18 . "github.com/onsi/gomega" 19 "github.com/replicatedhq/ship/pkg/constants" 20 "github.com/spf13/afero" 21 ) 22 23 var client *github.Client 24 var mux *http.ServeMux 25 var serverURL string 26 var teardown func() 27 28 func setupGitClient() (client *github.Client, mux *http.ServeMux, serveURL string, teardown func()) { 29 mux = http.NewServeMux() 30 server := httptest.NewServer(mux) 31 client = github.NewClient(nil) 32 url, _ := url.Parse(server.URL + "/") 33 client.BaseURL = url 34 client.UploadURL = url 35 36 return client, mux, server.URL, server.Close 37 } 38 39 func TestGithubClient(t *testing.T) { 40 RegisterFailHandler(Fail) 41 RunSpecs(t, "GithubClient") 42 } 43 44 var _ = Describe("GithubClient", func() { 45 client, mux, serverURL, teardown = setupGitClient() 46 redirectArchive := func(w http.ResponseWriter, r *http.Request) { 47 http.Redirect(w, r, serverURL+"/archive.tar.gz", http.StatusFound) 48 return 49 } 50 mux.HandleFunc("/repos/o/r/tarball/", redirectArchive) 51 mux.HandleFunc("/repos/o/r/tarball", redirectArchive) 52 53 mux.HandleFunc("/archive.tar.gz", func(w http.ResponseWriter, r *http.Request) { 54 archiveData := `H4sIAJKjXFsAA+3WXW6CQBQFYJbCBmrv/D831ce+uIOpDtGEKQaoibt3qERbEmiNI6TxfC8TIwkXTg65lfW73D3ZcrXZ7t1zcg9EZJRKv059OonL09lKmRDcMM6k0SkxSYolqbrLNB2fVW3LMIoPr2DounBZlg383z7H+fwnqp/5v25sWc8O1ucR7xHeh5ZyKH9xzl+TDPkroylJKeIMvR48//fw8PC4Ov1fLl7mb4uZX8e8xzX9V4Y1/RdMof9jyIpi6hFgQp3+1y78tLWrYm6CV+1/oum/JqGx/42hN/+12+XFwbuPsA7euA3++v1n/LL/sZA/JyM4vv9juMQ89SQwhd7+V67cb1fu5vInf9n/zLf+y6b/nDP0fwxtzFOPAQAAAAAAAAAAAACRHQEZehxJACgAAA==` 55 dec := base64.NewDecoder(base64.StdEncoding, strings.NewReader(archiveData)) 56 w.Header().Set("Content-Type", "application/gzip") 57 io.Copy(w, dec) 58 }) 59 60 Describe("GetFiles", func() { 61 Context("With a url prefixed with http(s)", func() { 62 It("should fetch and persist README.md and Chart.yaml", func() { 63 validGitURLWithPrefix := "http://www.github.com/o/r/" 64 mockFs := afero.Afero{Fs: afero.NewMemMapFs()} 65 gitClient := &GithubClient{ 66 Client: client, 67 Fs: mockFs, 68 Logger: log.NewNopLogger(), 69 } 70 71 dest, err := gitClient.GetFiles(context.Background(), validGitURLWithPrefix, constants.HelmChartPath) 72 Expect(err).NotTo(HaveOccurred()) 73 74 readme, err := gitClient.Fs.ReadFile(path.Join(dest, "README.md")) 75 Expect(err).NotTo(HaveOccurred()) 76 chart, err := gitClient.Fs.ReadFile(path.Join(dest, "Chart.yaml")) 77 Expect(err).NotTo(HaveOccurred()) 78 deployment, err := gitClient.Fs.ReadFile(path.Join(dest, "templates", "deployment.yml")) 79 Expect(err).NotTo(HaveOccurred()) 80 service, err := gitClient.Fs.ReadFile(path.Join(dest, "templates", "service.yml")) 81 Expect(err).NotTo(HaveOccurred()) 82 83 Expect(string(readme)).To(Equal("foo")) 84 Expect(string(chart)).To(Equal("bar")) 85 Expect(string(deployment)).To(Equal("deployment")) 86 Expect(string(service)).To(Equal("service")) 87 }) 88 }) 89 90 Context("With a url not prefixed with http", func() { 91 It("should fetch and persist README.md and Chart.yaml", func() { 92 validGitURLWithoutPrefix := "github.com/o/r" 93 mockFs := afero.Afero{Fs: afero.NewMemMapFs()} 94 gitClient := &GithubClient{ 95 Client: client, 96 Fs: mockFs, 97 Logger: log.NewNopLogger(), 98 } 99 100 dest, err := gitClient.GetFiles(context.Background(), validGitURLWithoutPrefix, constants.HelmChartPath) 101 Expect(err).NotTo(HaveOccurred()) 102 103 readme, err := gitClient.Fs.ReadFile(path.Join(dest, "README.md")) 104 Expect(err).NotTo(HaveOccurred()) 105 chart, err := gitClient.Fs.ReadFile(path.Join(dest, "Chart.yaml")) 106 Expect(err).NotTo(HaveOccurred()) 107 deployment, err := gitClient.Fs.ReadFile(path.Join(dest, "templates", "deployment.yml")) 108 Expect(err).NotTo(HaveOccurred()) 109 service, err := gitClient.Fs.ReadFile(path.Join(dest, "templates", "service.yml")) 110 Expect(err).NotTo(HaveOccurred()) 111 112 Expect(string(readme)).To(Equal("foo")) 113 Expect(string(chart)).To(Equal("bar")) 114 Expect(string(deployment)).To(Equal("deployment")) 115 Expect(string(service)).To(Equal("service")) 116 }) 117 }) 118 119 Context("With a non-github url", func() { 120 It("should return an error", func() { 121 nonGithubURL := "gitlab.com/o/r" 122 mockFs := afero.Afero{Fs: afero.NewMemMapFs()} 123 gitClient := &GithubClient{ 124 Client: client, 125 Fs: mockFs, 126 Logger: log.NewNopLogger(), 127 } 128 129 _, err := gitClient.GetFiles(context.Background(), nonGithubURL, constants.HelmChartPath) 130 Expect(err).NotTo(BeNil()) 131 Expect(err.Error()).To(Equal("http://gitlab.com/o/r is not a Github URL")) 132 }) 133 }) 134 135 Context("With a url path to a single file at the base of the repo", func() { 136 It("should fetch and persist the file", func() { 137 validGithubURLSingle := "github.com/o/r/blob/master/Chart.yaml" 138 mockFs := afero.Afero{Fs: afero.NewMemMapFs()} 139 gitClient := &GithubClient{ 140 Client: client, 141 Fs: mockFs, 142 Logger: log.NewNopLogger(), 143 } 144 145 dest, err := gitClient.GetFiles(context.Background(), validGithubURLSingle, constants.HelmChartPath) 146 Expect(err).NotTo(HaveOccurred()) 147 148 chart, err := gitClient.Fs.ReadFile(filepath.Join(dest, "Chart.yaml")) 149 Expect(err).NotTo(HaveOccurred()) 150 151 Expect(string(chart)).To(Equal("bar")) 152 }) 153 }) 154 155 Context("With a url path to a single nested file", func() { 156 It("should fetch and persist the file", func() { 157 validGithubURLSingle := "github.com/o/r/blob/master/templates/service.yml" 158 mockFs := afero.Afero{Fs: afero.NewMemMapFs()} 159 gitClient := &GithubClient{ 160 Client: client, 161 Fs: mockFs, 162 Logger: log.NewNopLogger(), 163 } 164 165 dest, err := gitClient.GetFiles(context.Background(), validGithubURLSingle, constants.HelmChartPath) 166 Expect(err).NotTo(HaveOccurred()) 167 chart, err := gitClient.Fs.ReadFile(filepath.Join(dest, "templates", "service.yml")) 168 Expect(err).NotTo(HaveOccurred()) 169 170 Expect(string(chart)).To(Equal("service")) 171 }) 172 }) 173 }) 174 175 Describe("decodeGitHubURL", func() { 176 Context("With a valid github url", func() { 177 It("should decode a valid url without a path", func() { 178 chartPath := "github.com/o/r" 179 o, r, b, p, err := decodeGitHubURL(chartPath) 180 Expect(err).NotTo(HaveOccurred()) 181 182 Expect(o).To(Equal("o")) 183 Expect(r).To(Equal("r")) 184 Expect(p).To(Equal("")) 185 Expect(b).To(Equal("")) 186 }) 187 188 It("should decode a valid url with a path", func() { 189 chartPath := "github.com/o/r/stable/chart" 190 o, r, b, p, err := decodeGitHubURL(chartPath) 191 Expect(err).NotTo(HaveOccurred()) 192 193 Expect(o).To(Equal("o")) 194 Expect(r).To(Equal("r")) 195 Expect(p).To(Equal("stable/chart")) 196 Expect(b).To(Equal("")) 197 }) 198 199 It("should decode a valid url with a /tree/<branch>/ path", func() { 200 chartPath := "github.com/o/r/tree/master/stable/chart" 201 o, r, b, p, err := decodeGitHubURL(chartPath) 202 Expect(err).NotTo(HaveOccurred()) 203 204 Expect(o).To(Equal("o")) 205 Expect(r).To(Equal("r")) 206 Expect(p).To(Equal("stable/chart")) 207 Expect(b).To(Equal("master")) 208 }) 209 }) 210 211 Context("With an invalid github url", func() { 212 It("should failed to decode a url without a path", func() { 213 chartPath := "github.com" 214 _, _, _, _, err := decodeGitHubURL(chartPath) 215 Expect(err).NotTo(BeNil()) 216 Expect(err.Error()).To(Equal("github.com: unable to decode github url")) 217 }) 218 219 It("should fail to decode a url with a path", func() { 220 chartPath := "github.com/o" 221 _, _, _, _, err := decodeGitHubURL(chartPath) 222 Expect(err).NotTo(BeNil()) 223 Expect(err.Error()).To(Equal("github.com/o: unable to decode github url")) 224 }) 225 }) 226 }) 227 228 }) 229 230 var _ = AfterSuite(func() { 231 teardown() 232 })