talos/internal/pkg/containers/image/resolver_test.go
Andrew Rynhard a10acd592a chore: address random CI nits
This PR does the following:

- updates the conform config
- cleans up conform scopes
- moves slash commands to the talos-bot
- adds a check list to the pull request template
- disables codecov comments
- uses `BOT_TOKEN` so all actions are performed as the talos-bot user
- adds a `make conformance` target to make it easy for contributors to
check their commit before creating a PR
- bumps golangci-lint to v1.24.0

Signed-off-by: Andrew Rynhard <andrew@andrewrynhard.com>
2020-04-13 13:01:14 -07:00

226 lines
7.6 KiB
Go

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package image_test
import (
"context"
"fmt"
"net/http"
"testing"
"github.com/stretchr/testify/suite"
"github.com/talos-systems/talos/internal/pkg/containers/image"
"github.com/talos-systems/talos/pkg/config/machine"
)
type mockConfig struct {
mirrors map[string]machine.RegistryMirrorConfig
config map[string]machine.RegistryConfig
}
func (c *mockConfig) Mirrors() map[string]machine.RegistryMirrorConfig {
return c.mirrors
}
func (c *mockConfig) Config() map[string]machine.RegistryConfig {
return c.config
}
func (c *mockConfig) ExtraFiles() ([]machine.File, error) {
return nil, fmt.Errorf("not implemented")
}
type ResolverSuite struct {
suite.Suite
}
func (suite *ResolverSuite) TestRegistryEndpoints() {
// defaults
endpoints, err := image.RegistryEndpoints(&mockConfig{}, "docker.io")
suite.Assert().NoError(err)
suite.Assert().Equal([]string{"https://registry-1.docker.io"}, endpoints)
endpoints, err = image.RegistryEndpoints(&mockConfig{}, "quay.io")
suite.Assert().NoError(err)
suite.Assert().Equal([]string{"https://quay.io"}, endpoints)
// overrides without catch-all
cfg := &mockConfig{
mirrors: map[string]machine.RegistryMirrorConfig{
"docker.io": {
Endpoints: []string{"http://127.0.0.1:5000", "https://some.host"},
},
},
}
endpoints, err = image.RegistryEndpoints(cfg, "docker.io")
suite.Assert().NoError(err)
suite.Assert().Equal([]string{"http://127.0.0.1:5000", "https://some.host"}, endpoints)
endpoints, err = image.RegistryEndpoints(cfg, "quay.io")
suite.Assert().NoError(err)
suite.Assert().Equal([]string{"https://quay.io"}, endpoints)
// overrides with catch-all
cfg = &mockConfig{
mirrors: map[string]machine.RegistryMirrorConfig{
"docker.io": {
Endpoints: []string{"http://127.0.0.1:5000", "https://some.host"},
},
"*": {
Endpoints: []string{"http://127.0.0.1:5001"},
},
},
}
endpoints, err = image.RegistryEndpoints(cfg, "docker.io")
suite.Assert().NoError(err)
suite.Assert().Equal([]string{"http://127.0.0.1:5000", "https://some.host"}, endpoints)
endpoints, err = image.RegistryEndpoints(cfg, "quay.io")
suite.Assert().NoError(err)
suite.Assert().Equal([]string{"http://127.0.0.1:5001"}, endpoints)
}
func (suite *ResolverSuite) TestPrepareAuth() {
user, pass, err := image.PrepareAuth(nil, "docker.io", "docker.io")
suite.Assert().NoError(err)
suite.Assert().Equal("", user)
suite.Assert().Equal("", pass)
user, pass, err = image.PrepareAuth(&machine.RegistryAuthConfig{
Username: "root",
Password: "secret",
}, "docker.io", "not.docker.io")
suite.Assert().NoError(err)
suite.Assert().Equal("", user)
suite.Assert().Equal("", pass)
user, pass, err = image.PrepareAuth(&machine.RegistryAuthConfig{
Username: "root",
Password: "secret",
}, "docker.io", "docker.io")
suite.Assert().NoError(err)
suite.Assert().Equal("root", user)
suite.Assert().Equal("secret", pass)
user, pass, err = image.PrepareAuth(&machine.RegistryAuthConfig{
IdentityToken: "xyz",
}, "docker.io", "docker.io")
suite.Assert().NoError(err)
suite.Assert().Equal("", user)
suite.Assert().Equal("xyz", pass)
user, pass, err = image.PrepareAuth(&machine.RegistryAuthConfig{
Auth: "dXNlcjE6c2VjcmV0MQ==",
}, "docker.io", "docker.io")
suite.Assert().NoError(err)
suite.Assert().Equal("user1", user)
suite.Assert().Equal("secret1", pass)
_, _, err = image.PrepareAuth(&machine.RegistryAuthConfig{}, "docker.io", "docker.io")
suite.Assert().EqualError(err, "invalid auth config for \"docker.io\"")
}
func (suite *ResolverSuite) TestRegistryHosts() {
registryHosts, err := image.RegistryHosts(&mockConfig{})("docker.io")
suite.Require().NoError(err)
suite.Assert().Len(registryHosts, 1)
suite.Assert().Equal("https", registryHosts[0].Scheme)
suite.Assert().Equal("registry-1.docker.io", registryHosts[0].Host)
suite.Assert().Equal("/v2", registryHosts[0].Path)
suite.Assert().Nil(registryHosts[0].Client.Transport.(*http.Transport).TLSClientConfig) //nolint: errcheck
cfg := &mockConfig{
mirrors: map[string]machine.RegistryMirrorConfig{
"docker.io": {
Endpoints: []string{"http://127.0.0.1:5000/docker.io", "https://some.host"},
},
},
}
registryHosts, err = image.RegistryHosts(cfg)("docker.io")
suite.Require().NoError(err)
suite.Assert().Len(registryHosts, 2)
suite.Assert().Equal("http", registryHosts[0].Scheme)
suite.Assert().Equal("127.0.0.1:5000", registryHosts[0].Host)
suite.Assert().Equal("/docker.io", registryHosts[0].Path)
suite.Assert().Nil(registryHosts[0].Client.Transport.(*http.Transport).TLSClientConfig) //nolint: errcheck
suite.Assert().Equal("https", registryHosts[1].Scheme)
suite.Assert().Equal("some.host", registryHosts[1].Host)
suite.Assert().Equal("/v2", registryHosts[1].Path)
suite.Assert().Nil(registryHosts[1].Client.Transport.(*http.Transport).TLSClientConfig) //nolint: errcheck
cfg = &mockConfig{
mirrors: map[string]machine.RegistryMirrorConfig{
"docker.io": {
Endpoints: []string{"https://some.host:123"},
},
},
config: map[string]machine.RegistryConfig{
"some.host:123": {
TLS: &machine.RegistryTLSConfig{
CA: []byte(caCertMock),
// ClientIdentity: &x509.PEMEncodedCertificateAndKey{},
},
Auth: &machine.RegistryAuthConfig{
Username: "root",
Password: "secret",
},
},
},
}
registryHosts, err = image.RegistryHosts(cfg)("docker.io")
suite.Require().NoError(err)
suite.Assert().Len(registryHosts, 1)
suite.Assert().Equal("https", registryHosts[0].Scheme)
suite.Assert().Equal("some.host:123", registryHosts[0].Host)
suite.Assert().Equal("/v2", registryHosts[0].Path)
tlsClientConfig := registryHosts[0].Client.Transport.(*http.Transport).TLSClientConfig //nolint: errcheck
suite.Require().NotNil(tlsClientConfig)
suite.Require().NotNil(tlsClientConfig.RootCAs)
suite.Require().Empty(tlsClientConfig.Certificates)
suite.Require().NotNil(registryHosts[0].Authorizer)
req, err := http.NewRequest("GET", "htts://some.host:123/v2", nil)
suite.Require().NoError(err)
resp := &http.Response{}
resp.Request = req
resp.Header = http.Header{}
resp.Header.Add("WWW-Authenticate", "Basic realm=\"Access to the staging site\", charset=\"UTF-8\"")
suite.Require().NoError(registryHosts[0].Authorizer.AddResponses(context.Background(), []*http.Response{resp}))
suite.Require().NoError(registryHosts[0].Authorizer.Authorize(context.Background(), req))
suite.Assert().Equal("Basic cm9vdDpzZWNyZXQ=", req.Header.Get("Authorization"))
}
func TestResolverSuite(t *testing.T) {
suite.Run(t, new(ResolverSuite))
}
const caCertMock = `-----BEGIN CERTIFICATE-----
MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC
VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T
U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0
aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz
WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0
b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS
b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB
BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI
7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg
CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud
EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD
VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T
kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+
gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl
-----END CERTIFICATE-----
`