github.com/umeshredd/helm@v3.0.0-alpha.1+incompatible/pkg/registry/client_test.go (about) 1 /* 2 Copyright The Helm 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 registry 18 19 import ( 20 "bytes" 21 "context" 22 "fmt" 23 "io" 24 "io/ioutil" 25 "net" 26 "os" 27 "path/filepath" 28 "testing" 29 "time" 30 31 auth "github.com/deislabs/oras/pkg/auth/docker" 32 "github.com/docker/distribution/configuration" 33 "github.com/docker/distribution/registry" 34 _ "github.com/docker/distribution/registry/auth/htpasswd" 35 _ "github.com/docker/distribution/registry/storage/driver/inmemory" 36 "github.com/stretchr/testify/suite" 37 "golang.org/x/crypto/bcrypt" 38 39 "helm.sh/helm/pkg/chart" 40 ) 41 42 var ( 43 testCacheRootDir = "helm-registry-test" 44 testHtpasswdFileBasename = "authtest.htpasswd" 45 testUsername = "myuser" 46 testPassword = "mypass" 47 ) 48 49 type RegistryClientTestSuite struct { 50 suite.Suite 51 Out io.Writer 52 DockerRegistryHost string 53 CacheRootDir string 54 RegistryClient *Client 55 } 56 57 func (suite *RegistryClientTestSuite) SetupSuite() { 58 suite.CacheRootDir = testCacheRootDir 59 os.RemoveAll(suite.CacheRootDir) 60 os.Mkdir(suite.CacheRootDir, 0700) 61 62 var out bytes.Buffer 63 suite.Out = &out 64 credentialsFile := filepath.Join(suite.CacheRootDir, CredentialsFileBasename) 65 66 client, err := auth.NewClient(credentialsFile) 67 suite.Nil(err, "no error creating auth client") 68 69 resolver, err := client.Resolver(context.Background()) 70 suite.Nil(err, "no error creating resolver") 71 72 // Init test client 73 suite.RegistryClient = NewClient(&ClientOptions{ 74 Debug: false, 75 Out: suite.Out, 76 Authorizer: Authorizer{ 77 Client: client, 78 }, 79 Resolver: Resolver{ 80 Resolver: resolver, 81 }, 82 CacheRootDir: suite.CacheRootDir, 83 }) 84 85 // create htpasswd file (w BCrypt, which is required) 86 pwBytes, err := bcrypt.GenerateFromPassword([]byte(testPassword), bcrypt.DefaultCost) 87 suite.Nil(err, "no error generating bcrypt password for test htpasswd file") 88 htpasswdPath := filepath.Join(suite.CacheRootDir, testHtpasswdFileBasename) 89 err = ioutil.WriteFile(htpasswdPath, []byte(fmt.Sprintf("%s:%s\n", testUsername, string(pwBytes))), 0644) 90 suite.Nil(err, "no error creating test htpasswd file") 91 92 // Registry config 93 config := &configuration.Configuration{} 94 port, err := getFreePort() 95 suite.Nil(err, "no error finding free port for test registry") 96 suite.DockerRegistryHost = fmt.Sprintf("localhost:%d", port) 97 config.HTTP.Addr = fmt.Sprintf(":%d", port) 98 config.HTTP.DrainTimeout = time.Duration(10) * time.Second 99 config.Storage = map[string]configuration.Parameters{"inmemory": map[string]interface{}{}} 100 config.Auth = configuration.Auth{ 101 "htpasswd": configuration.Parameters{ 102 "realm": "localhost", 103 "path": htpasswdPath, 104 }, 105 } 106 dockerRegistry, err := registry.NewRegistry(context.Background(), config) 107 suite.Nil(err, "no error creating test registry") 108 109 // Start Docker registry 110 go dockerRegistry.ListenAndServe() 111 } 112 113 func (suite *RegistryClientTestSuite) TearDownSuite() { 114 os.RemoveAll(suite.CacheRootDir) 115 } 116 117 func (suite *RegistryClientTestSuite) Test_0_Login() { 118 err := suite.RegistryClient.Login(suite.DockerRegistryHost, "badverybad", "ohsobad") 119 suite.NotNil(err, "error logging into registry with bad credentials") 120 121 err = suite.RegistryClient.Login(suite.DockerRegistryHost, testUsername, testPassword) 122 suite.Nil(err, "no error logging into registry with good credentials") 123 } 124 125 func (suite *RegistryClientTestSuite) Test_1_SaveChart() { 126 ref, err := ParseReference(fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost)) 127 suite.Nil(err) 128 129 // empty chart 130 err = suite.RegistryClient.SaveChart(&chart.Chart{}, ref) 131 suite.NotNil(err) 132 133 // valid chart 134 ch := &chart.Chart{} 135 ch.Metadata = &chart.Metadata{ 136 APIVersion: "v1", 137 Name: "testchart", 138 Version: "1.2.3", 139 } 140 err = suite.RegistryClient.SaveChart(ch, ref) 141 suite.Nil(err) 142 } 143 144 func (suite *RegistryClientTestSuite) Test_2_LoadChart() { 145 146 // non-existent ref 147 ref, err := ParseReference(fmt.Sprintf("%s/testrepo/whodis:9.9.9", suite.DockerRegistryHost)) 148 suite.Nil(err) 149 ch, err := suite.RegistryClient.LoadChart(ref) 150 suite.NotNil(err) 151 152 // existing ref 153 ref, err = ParseReference(fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost)) 154 suite.Nil(err) 155 ch, err = suite.RegistryClient.LoadChart(ref) 156 suite.Nil(err) 157 suite.Equal("testchart", ch.Metadata.Name) 158 suite.Equal("1.2.3", ch.Metadata.Version) 159 } 160 161 func (suite *RegistryClientTestSuite) Test_3_PushChart() { 162 163 // non-existent ref 164 ref, err := ParseReference(fmt.Sprintf("%s/testrepo/whodis:9.9.9", suite.DockerRegistryHost)) 165 suite.Nil(err) 166 err = suite.RegistryClient.PushChart(ref) 167 suite.NotNil(err) 168 169 // existing ref 170 ref, err = ParseReference(fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost)) 171 suite.Nil(err) 172 err = suite.RegistryClient.PushChart(ref) 173 suite.Nil(err) 174 } 175 176 func (suite *RegistryClientTestSuite) Test_4_PullChart() { 177 178 // non-existent ref 179 ref, err := ParseReference(fmt.Sprintf("%s/testrepo/whodis:9.9.9", suite.DockerRegistryHost)) 180 suite.Nil(err) 181 err = suite.RegistryClient.PullChart(ref) 182 suite.NotNil(err) 183 184 // existing ref 185 ref, err = ParseReference(fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost)) 186 suite.Nil(err) 187 err = suite.RegistryClient.PullChart(ref) 188 suite.Nil(err) 189 } 190 191 func (suite *RegistryClientTestSuite) Test_5_PrintChartTable() { 192 err := suite.RegistryClient.PrintChartTable() 193 suite.Nil(err) 194 } 195 196 func (suite *RegistryClientTestSuite) Test_6_RemoveChart() { 197 198 // non-existent ref 199 ref, err := ParseReference(fmt.Sprintf("%s/testrepo/whodis:9.9.9", suite.DockerRegistryHost)) 200 suite.Nil(err) 201 err = suite.RegistryClient.RemoveChart(ref) 202 suite.NotNil(err) 203 204 // existing ref 205 ref, err = ParseReference(fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost)) 206 suite.Nil(err) 207 err = suite.RegistryClient.RemoveChart(ref) 208 suite.Nil(err) 209 } 210 211 func (suite *RegistryClientTestSuite) Test_7_Logout() { 212 err := suite.RegistryClient.Logout("this-host-aint-real:5000") 213 suite.NotNil(err, "error logging out of registry that has no entry") 214 215 err = suite.RegistryClient.Logout(suite.DockerRegistryHost) 216 suite.Nil(err, "no error logging out of registry") 217 } 218 219 func TestRegistryClientTestSuite(t *testing.T) { 220 suite.Run(t, new(RegistryClientTestSuite)) 221 } 222 223 // borrowed from https://github.com/phayes/freeport 224 func getFreePort() (int, error) { 225 addr, err := net.ResolveTCPAddr("tcp", "localhost:0") 226 if err != nil { 227 return 0, err 228 } 229 230 l, err := net.ListenTCP("tcp", addr) 231 if err != nil { 232 return 0, err 233 } 234 defer l.Close() 235 return l.Addr().(*net.TCPAddr).Port, nil 236 }