Merge "Add implementation of document/repo interface"
This commit is contained in:
commit
ad9ee69cce
@ -821,8 +821,9 @@ func (m *Manifest) Equal(n *Manifest) bool {
|
|||||||
if n == nil {
|
if n == nil {
|
||||||
return n == m
|
return n == m
|
||||||
}
|
}
|
||||||
repositoryEq := reflect.DeepEqual(m.Repositories, n.Repositories)
|
repositoryEq := reflect.DeepEqual(m.Repository, n.Repository)
|
||||||
return repositoryEq && m.TargetPath == n.TargetPath
|
extraReposEq := reflect.DeepEqual(m.ExtraRepositories, n.ExtraRepositories)
|
||||||
|
return repositoryEq && extraReposEq && m.TargetPath == n.TargetPath
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manifest) String() string {
|
func (m *Manifest) String() string {
|
||||||
@ -833,30 +834,6 @@ func (m *Manifest) String() string {
|
|||||||
return string(yamlData)
|
return string(yamlData)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repository functions
|
|
||||||
func (r *Repository) Equal(s *Repository) bool {
|
|
||||||
if s == nil {
|
|
||||||
return r == s
|
|
||||||
}
|
|
||||||
var urlMatches bool
|
|
||||||
if r.Url != nil && s.Url != nil {
|
|
||||||
urlMatches = r.Url.String() == s.Url.String()
|
|
||||||
} else {
|
|
||||||
// this catches cases where one or both are nil
|
|
||||||
urlMatches = r.Url == s.Url
|
|
||||||
}
|
|
||||||
return urlMatches &&
|
|
||||||
r.Username == s.Username &&
|
|
||||||
r.TargetPath == s.TargetPath
|
|
||||||
}
|
|
||||||
func (r *Repository) String() string {
|
|
||||||
yamlData, err := yaml.Marshal(&r)
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return string(yamlData)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modules functions
|
// Modules functions
|
||||||
func (m *Modules) Equal(n *Modules) bool {
|
func (m *Modules) Equal(n *Modules) bool {
|
||||||
if n == nil {
|
if n == nil {
|
||||||
|
@ -68,6 +68,14 @@ func TestString(t *testing.T) {
|
|||||||
name: "repository",
|
name: "repository",
|
||||||
stringer: DummyRepository(),
|
stringer: DummyRepository(),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "repo-auth",
|
||||||
|
stringer: DummyRepoAuth(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "repo-checkout",
|
||||||
|
stringer: DummyRepoCheckout(),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "bootstrap",
|
name: "bootstrap",
|
||||||
stringer: DummyBootstrap(),
|
stringer: DummyBootstrap(),
|
||||||
@ -157,12 +165,28 @@ func TestEqual(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("repository-equal", func(t *testing.T) {
|
t.Run("repository-equal", func(t *testing.T) {
|
||||||
testRepository1 := &Repository{TargetPath: "same"}
|
testRepository1 := &Repository{URLString: "same"}
|
||||||
testRepository2 := &Repository{TargetPath: "different"}
|
testRepository2 := &Repository{URLString: "different"}
|
||||||
assert.True(t, testRepository1.Equal(testRepository1))
|
assert.True(t, testRepository1.Equal(testRepository1))
|
||||||
assert.False(t, testRepository1.Equal(testRepository2))
|
assert.False(t, testRepository1.Equal(testRepository2))
|
||||||
assert.False(t, testRepository1.Equal(nil))
|
assert.False(t, testRepository1.Equal(nil))
|
||||||
})
|
})
|
||||||
|
t.Run("auth-equal", func(t *testing.T) {
|
||||||
|
testSpec1 := &RepoAuth{}
|
||||||
|
testSpec2 := &RepoAuth{}
|
||||||
|
testSpec2.Type = "ssh-key"
|
||||||
|
assert.True(t, testSpec1.Equal(testSpec1))
|
||||||
|
assert.False(t, testSpec1.Equal(testSpec2))
|
||||||
|
assert.False(t, testSpec1.Equal(nil))
|
||||||
|
})
|
||||||
|
t.Run("checkout-equal", func(t *testing.T) {
|
||||||
|
testSpec1 := &RepoCheckout{}
|
||||||
|
testSpec2 := &RepoCheckout{}
|
||||||
|
testSpec2.Branch = "Master"
|
||||||
|
assert.True(t, testSpec1.Equal(testSpec1))
|
||||||
|
assert.False(t, testSpec1.Equal(testSpec2))
|
||||||
|
assert.False(t, testSpec1.Equal(nil))
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("modules-equal", func(t *testing.T) {
|
t.Run("modules-equal", func(t *testing.T) {
|
||||||
testModules1 := NewModules()
|
testModules1 := NewModules()
|
||||||
|
@ -2,8 +2,54 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Repo errors
|
||||||
|
|
||||||
|
// ErrMutuallyExclusiveAuthSSHPass is returned when ssh-pass type
|
||||||
|
// is selected and http-pass, ssh-key or key-pass options are defined
|
||||||
|
type ErrIncompatibleAuthOptions struct {
|
||||||
|
ForbiddenOptions []string
|
||||||
|
AuthType string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewErrIncompetibleAuthOptions(fo []string, ao string) error {
|
||||||
|
return ErrIncompatibleAuthOptions{
|
||||||
|
ForbiddenOptions: fo,
|
||||||
|
AuthType: ao,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ErrIncompatibleAuthOptions) Error() string {
|
||||||
|
return fmt.Sprintf("Can not use %s options, with auth type %s", e.ForbiddenOptions, e.AuthType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrAuthTypeNotSupported is returned with wrong AuthType is provided
|
||||||
|
type ErrAuthTypeNotSupported struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ErrAuthTypeNotSupported) Error() string {
|
||||||
|
return "Invalid auth, allowed types: " + strings.Join(AllowedAuthTypes, ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrRepoSpecRequiresURL is returned when repository URL is not specified
|
||||||
|
type ErrRepoSpecRequiresURL struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ErrRepoSpecRequiresURL) Error() string {
|
||||||
|
return "Repostory spec requires url"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrMutuallyExclusiveCheckout is returned if
|
||||||
|
// mutually exclusive options are given as checkout options
|
||||||
|
type ErrMutuallyExclusiveCheckout struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ErrMutuallyExclusiveCheckout) Error() string {
|
||||||
|
return "Chekout mutually execlusive, use either: commit-hash, branch or tag"
|
||||||
|
}
|
||||||
|
|
||||||
// ErrBootstrapInfoNotFound returned if bootstrap
|
// ErrBootstrapInfoNotFound returned if bootstrap
|
||||||
// information is not found for cluster
|
// information is not found for cluster
|
||||||
type ErrBootstrapInfoNotFound struct {
|
type ErrBootstrapInfoNotFound struct {
|
||||||
|
202
pkg/config/repo.go
Normal file
202
pkg/config/repo.go
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"gopkg.in/src-d/go-git.v4"
|
||||||
|
"gopkg.in/src-d/go-git.v4/plumbing"
|
||||||
|
"gopkg.in/src-d/go-git.v4/plumbing/transport"
|
||||||
|
"gopkg.in/src-d/go-git.v4/plumbing/transport/http"
|
||||||
|
"gopkg.in/src-d/go-git.v4/plumbing/transport/ssh"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
|
||||||
|
"opendev.org/airship/airshipctl/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SSHAuth = "ssh-key"
|
||||||
|
SSHPass = "ssh-pass"
|
||||||
|
HTTPBasic = "http-basic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RepoCheckout methods
|
||||||
|
|
||||||
|
func (c *RepoCheckout) Equal(s *RepoCheckout) bool {
|
||||||
|
if s == nil {
|
||||||
|
return s == c
|
||||||
|
}
|
||||||
|
return c.CommitHash == s.CommitHash &&
|
||||||
|
c.Branch == s.Branch &&
|
||||||
|
c.Tag == s.Tag &&
|
||||||
|
c.RemoteRef == s.RemoteRef
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RepoCheckout) String() string {
|
||||||
|
yaml, err := yaml.Marshal(&r)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(yaml)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RepoCheckout) Validate() error {
|
||||||
|
possibleValues := []string{c.CommitHash, c.Branch, c.Tag, c.RemoteRef}
|
||||||
|
var count int
|
||||||
|
for _, val := range possibleValues {
|
||||||
|
if val != "" {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if count > 1 {
|
||||||
|
return ErrMutuallyExclusiveCheckout{}
|
||||||
|
}
|
||||||
|
if c.RemoteRef != "" {
|
||||||
|
return fmt.Errorf("Repository checkout by RemoteRef is not yet implemented\n%w", errors.ErrNotImplemented{})
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RepoAuth methods
|
||||||
|
var (
|
||||||
|
AllowedAuthTypes = []string{SSHAuth, SSHPass, HTTPBasic}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (auth *RepoAuth) Equal(s *RepoAuth) bool {
|
||||||
|
if s == nil {
|
||||||
|
return s == auth
|
||||||
|
}
|
||||||
|
return auth.Type == s.Type &&
|
||||||
|
auth.KeyPassword == s.KeyPassword &&
|
||||||
|
auth.KeyPath == s.KeyPath &&
|
||||||
|
auth.SSHPassword == s.SSHPassword &&
|
||||||
|
auth.Username == s.Username
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RepoAuth) String() string {
|
||||||
|
yaml, err := yaml.Marshal(&r)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(yaml)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (auth *RepoAuth) Validate() error {
|
||||||
|
if !stringInSlice(auth.Type, AllowedAuthTypes) {
|
||||||
|
return ErrAuthTypeNotSupported{}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch auth.Type {
|
||||||
|
case SSHAuth:
|
||||||
|
if auth.HTTPPassword != "" || auth.SSHPassword != "" {
|
||||||
|
return NewErrIncompetibleAuthOptions([]string{"http-pass, ssh-pass"}, auth.Type)
|
||||||
|
}
|
||||||
|
case HTTPBasic:
|
||||||
|
if auth.SSHPassword != "" || auth.KeyPath != "" || auth.KeyPassword != "" {
|
||||||
|
return NewErrIncompetibleAuthOptions([]string{"ssh-pass, ssh-key, key-pass"}, auth.Type)
|
||||||
|
}
|
||||||
|
case SSHPass:
|
||||||
|
if auth.KeyPath != "" || auth.KeyPassword != "" || auth.HTTPPassword != "" {
|
||||||
|
return NewErrIncompetibleAuthOptions([]string{"ssh-key, key-pass, http-pass"}, auth.Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringInSlice(a string, list []string) bool {
|
||||||
|
for _, b := range list {
|
||||||
|
if b == a {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repository functions
|
||||||
|
// Equal compares repository specs
|
||||||
|
func (repo *Repository) Equal(s *Repository) bool {
|
||||||
|
if s == nil {
|
||||||
|
return s == repo
|
||||||
|
}
|
||||||
|
|
||||||
|
return repo.URLString == s.URLString &&
|
||||||
|
reflect.DeepEqual(s.Auth, repo.Auth) &&
|
||||||
|
reflect.DeepEqual(s.CheckoutOptions, repo.CheckoutOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Repository) String() string {
|
||||||
|
yaml, err := yaml.Marshal(&r)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(yaml)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (spec *Repository) Validate() error {
|
||||||
|
if spec.URLString == "" {
|
||||||
|
return ErrRepoSpecRequiresURL{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if spec.Auth != nil {
|
||||||
|
err := spec.Auth.Validate()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if spec.CheckoutOptions != nil {
|
||||||
|
err := spec.CheckoutOptions.Validate()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *Repository) ToAuth() (transport.AuthMethod, error) {
|
||||||
|
if repo.Auth == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
switch repo.Auth.Type {
|
||||||
|
case SSHAuth:
|
||||||
|
return ssh.NewPublicKeysFromFile(repo.Auth.Username, repo.Auth.KeyPath, repo.Auth.KeyPassword)
|
||||||
|
case SSHPass:
|
||||||
|
return &ssh.Password{User: repo.Auth.Username, Password: repo.Auth.HTTPPassword}, nil
|
||||||
|
case HTTPBasic:
|
||||||
|
return &http.BasicAuth{Username: repo.Auth.Username, Password: repo.Auth.HTTPPassword}, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("Error building auth opts, repo\n%s\n: %w", repo.String(), errors.ErrNotImplemented{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *Repository) ToCheckoutOptions(force bool) *git.CheckoutOptions {
|
||||||
|
co := &git.CheckoutOptions{
|
||||||
|
Force: force,
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case repo.CheckoutOptions == nil:
|
||||||
|
case repo.CheckoutOptions.Branch != "":
|
||||||
|
co.Branch = plumbing.NewBranchReferenceName(repo.CheckoutOptions.Branch)
|
||||||
|
case repo.CheckoutOptions.Tag != "":
|
||||||
|
co.Branch = plumbing.NewTagReferenceName(repo.CheckoutOptions.Tag)
|
||||||
|
case repo.CheckoutOptions.CommitHash != "":
|
||||||
|
co.Hash = plumbing.NewHash(repo.CheckoutOptions.CommitHash)
|
||||||
|
}
|
||||||
|
return co
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *Repository) ToCloneOptions(auth transport.AuthMethod) *git.CloneOptions {
|
||||||
|
return &git.CloneOptions{
|
||||||
|
Auth: auth,
|
||||||
|
URL: repo.URLString,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *Repository) ToFetchOptions(auth transport.AuthMethod) *git.FetchOptions {
|
||||||
|
return &git.FetchOptions{Auth: auth}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *Repository) URL() string {
|
||||||
|
return repo.URLString
|
||||||
|
}
|
261
pkg/config/repo_test.go
Normal file
261
pkg/config/repo_test.go
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
validateTestName = "ToCheckout"
|
||||||
|
validateFailuresTestName = "Validate"
|
||||||
|
toAuthTestName = "ToAuth"
|
||||||
|
toAuthNilTestName = "ToAuthNil"
|
||||||
|
ToFetchOptionsTestName = "ToFetchOptions"
|
||||||
|
toAuthNilError = "toAuthNilError"
|
||||||
|
URLTestName = "URLTest"
|
||||||
|
StringTestData = `test-data:
|
||||||
|
no-auth:
|
||||||
|
url: https://github.com/src-d/go-git.git
|
||||||
|
checkout:
|
||||||
|
tag: v3.0.0
|
||||||
|
ssh-key-auth:
|
||||||
|
url: git@github.com:src-d/go-git.git
|
||||||
|
auth:
|
||||||
|
type: ssh-key
|
||||||
|
ssh-key: "testdata/test-key.pem"
|
||||||
|
username: git
|
||||||
|
checkout:
|
||||||
|
branch: master
|
||||||
|
ssh-pass:
|
||||||
|
url: /home/ubuntu/some-gitrepo
|
||||||
|
auth:
|
||||||
|
type: ssh-pass
|
||||||
|
ssh-pass: "qwerty123"
|
||||||
|
username: deployer
|
||||||
|
checkout:
|
||||||
|
commit-hash: 01c4f7f32beb9851ae8f119a6b8e497d2b1e2bb8
|
||||||
|
http-basic-auth:
|
||||||
|
url: /home/ubuntu/some-gitrepo
|
||||||
|
auth:
|
||||||
|
type: http-basic
|
||||||
|
http-pass: "qwerty123"
|
||||||
|
username: deployer
|
||||||
|
checkout:
|
||||||
|
commit-hash: 01c4f7f32beb9851ae8f119a6b8e497d2b1e2bb8
|
||||||
|
empty-checkout:
|
||||||
|
url: /home/ubuntu/some-gitrepo
|
||||||
|
auth:
|
||||||
|
type: http-basic
|
||||||
|
http-pass: "qwerty123"
|
||||||
|
username: deployer
|
||||||
|
wrong-type-auth:
|
||||||
|
url: /home/ubuntu/some-gitrepo
|
||||||
|
auth:
|
||||||
|
type: wrong-type
|
||||||
|
http-pass: "qwerty123"
|
||||||
|
username: deployer
|
||||||
|
checkout:
|
||||||
|
commit-hash: 01c4f7f32beb9851ae8f119a6b8e497d2b1e2bb8
|
||||||
|
mutually-exclusive-auth-opts:
|
||||||
|
url: /home/ubuntu/some-gitrepo
|
||||||
|
auth:
|
||||||
|
type: http-basic
|
||||||
|
ssh-key: "/path-to-key"
|
||||||
|
username: deployer
|
||||||
|
mutually-exclusive-checkout-opts:
|
||||||
|
url: /home/ubuntu/some-gitrepo
|
||||||
|
checkout:
|
||||||
|
commit-hash: 01c4f7f32beb9851ae8f119a6b8e497d2b1e2bb8
|
||||||
|
branch: master
|
||||||
|
mutually-exclusive-auth-opts-ssh-key:
|
||||||
|
url: /home/ubuntu/some-gitrepo
|
||||||
|
auth:
|
||||||
|
type: ssh-key
|
||||||
|
http-pass: "qwerty123"
|
||||||
|
ssh-key: "/path-to-key"
|
||||||
|
username: deployer
|
||||||
|
checkout:
|
||||||
|
commit-hash: 01c4f7f32beb9851ae8f119a6b8e497d2b1e2bb8
|
||||||
|
mutually-exclusive-auth-opts-ssh-pass:
|
||||||
|
url: /home/ubuntu/some-gitrepo
|
||||||
|
auth:
|
||||||
|
type: ssh-pass
|
||||||
|
ssh-pass: "qwerty123"
|
||||||
|
http-pass: "qwerty123"
|
||||||
|
ssh-key: "/path-to-key"
|
||||||
|
username: deployer
|
||||||
|
checkout:
|
||||||
|
commit-hash: 01c4f7f32beb9851ae8f119a6b8e497d2b1e2bb8`
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
TestCaseMap = map[string]*TestCase{
|
||||||
|
validateTestName: {
|
||||||
|
expectError: false,
|
||||||
|
dataMapEntry: []string{"http-basic-auth", "ssh-key-auth", "no-auth", "empty-checkout"},
|
||||||
|
expectedNil: false,
|
||||||
|
},
|
||||||
|
validateFailuresTestName: {
|
||||||
|
expectError: true,
|
||||||
|
dataMapEntry: []string{"wrong-type-auth",
|
||||||
|
"mutually-exclusive-auth-opts",
|
||||||
|
"mutually-exclusive-checkout-opts",
|
||||||
|
"mutually-exclusive-auth-opts-ssh-key",
|
||||||
|
"mutually-exclusive-auth-opts-ssh-pass"},
|
||||||
|
expectedNil: false,
|
||||||
|
},
|
||||||
|
toAuthTestName: {
|
||||||
|
expectError: false,
|
||||||
|
dataMapEntry: []string{"ssh-key-auth",
|
||||||
|
"http-basic-auth",
|
||||||
|
"ssh-pass"},
|
||||||
|
|
||||||
|
expectedNil: false,
|
||||||
|
},
|
||||||
|
toAuthNilError: {
|
||||||
|
expectError: true,
|
||||||
|
dataMapEntry: []string{"wrong-type-auth"},
|
||||||
|
expectedNil: true,
|
||||||
|
},
|
||||||
|
toAuthNilTestName: {
|
||||||
|
expectError: false,
|
||||||
|
dataMapEntry: []string{"no-auth"},
|
||||||
|
expectedNil: true,
|
||||||
|
},
|
||||||
|
ToFetchOptionsTestName: {
|
||||||
|
expectError: false,
|
||||||
|
dataMapEntry: []string{"no-auth"},
|
||||||
|
expectedNil: false,
|
||||||
|
},
|
||||||
|
URLTestName: {
|
||||||
|
expectError: false,
|
||||||
|
expectedNil: false,
|
||||||
|
dataMapEntry: []string{"no-auth"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type TestCase struct {
|
||||||
|
expectError bool
|
||||||
|
// this maps to TestData map in TestRepos struct
|
||||||
|
dataMapEntry []string
|
||||||
|
expectedNil bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestRepos struct {
|
||||||
|
TestData map[string]*Repository `json:"test-data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToCheckout(t *testing.T) {
|
||||||
|
data := &TestRepos{}
|
||||||
|
err := yaml.Unmarshal([]byte(StringTestData), data)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testCase := TestCaseMap[validateTestName]
|
||||||
|
|
||||||
|
for _, name := range testCase.dataMapEntry {
|
||||||
|
repo := data.TestData[name]
|
||||||
|
require.NotNil(t, repo)
|
||||||
|
co := repo.ToCheckoutOptions(false)
|
||||||
|
if testCase.expectedNil {
|
||||||
|
assert.Nil(t, co)
|
||||||
|
} else {
|
||||||
|
assert.NotNil(t, co)
|
||||||
|
assert.NoError(t, co.Validate())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToAuth(t *testing.T) {
|
||||||
|
data := &TestRepos{}
|
||||||
|
err := yaml.Unmarshal([]byte(StringTestData), data)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
for _, testCaseName := range []string{toAuthTestName, toAuthNilTestName, toAuthNilError} {
|
||||||
|
testCase := TestCaseMap[testCaseName]
|
||||||
|
for _, name := range testCase.dataMapEntry {
|
||||||
|
repo := data.TestData[name]
|
||||||
|
auth, authErr := repo.ToAuth()
|
||||||
|
if testCase.expectError {
|
||||||
|
assert.Error(t, authErr)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, authErr)
|
||||||
|
}
|
||||||
|
if testCase.expectedNil {
|
||||||
|
assert.Nil(t, auth)
|
||||||
|
} else {
|
||||||
|
assert.NotNil(t, auth)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateRepository(t *testing.T) {
|
||||||
|
data := &TestRepos{}
|
||||||
|
err := yaml.Unmarshal([]byte(StringTestData), data)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
for _, testCaseName := range []string{validateTestName, validateFailuresTestName} {
|
||||||
|
testCase := TestCaseMap[testCaseName]
|
||||||
|
for _, name := range testCase.dataMapEntry {
|
||||||
|
repo := data.TestData[name]
|
||||||
|
err := repo.Validate()
|
||||||
|
if testCase.expectError {
|
||||||
|
assert.Error(t, err)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
if testCase.expectedNil {
|
||||||
|
assert.Nil(t, repo)
|
||||||
|
} else {
|
||||||
|
assert.NotNil(t, repo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToFetchOptions(t *testing.T) {
|
||||||
|
data := &TestRepos{}
|
||||||
|
err := yaml.Unmarshal([]byte(StringTestData), data)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testCase := TestCaseMap[ToFetchOptionsTestName]
|
||||||
|
|
||||||
|
for _, name := range testCase.dataMapEntry {
|
||||||
|
repo := data.TestData[name]
|
||||||
|
require.NotNil(t, repo)
|
||||||
|
assert.NotNil(t, repo.ToFetchOptions(nil))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToCloneOptions(t *testing.T) {
|
||||||
|
data := &TestRepos{}
|
||||||
|
err := yaml.Unmarshal([]byte(StringTestData), data)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testCase := TestCaseMap[ToFetchOptionsTestName]
|
||||||
|
|
||||||
|
for _, name := range testCase.dataMapEntry {
|
||||||
|
repo := data.TestData[name]
|
||||||
|
require.NotNil(t, repo)
|
||||||
|
assert.NotNil(t, repo.ToCloneOptions(nil))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestURL(t *testing.T) {
|
||||||
|
data := &TestRepos{}
|
||||||
|
err := yaml.Unmarshal([]byte(StringTestData), data)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testCase := TestCaseMap[URLTestName]
|
||||||
|
|
||||||
|
for _, name := range testCase.dataMapEntry {
|
||||||
|
repo := data.TestData[name]
|
||||||
|
require.NotNil(t, repo)
|
||||||
|
assert.Equal(t, repo.URLString, repo.URL())
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,6 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/url"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -86,19 +85,34 @@ func DummyCluster() *Cluster {
|
|||||||
func DummyManifest() *Manifest {
|
func DummyManifest() *Manifest {
|
||||||
m := NewManifest()
|
m := NewManifest()
|
||||||
// Repositories is the map of repository adddressable by a name
|
// Repositories is the map of repository adddressable by a name
|
||||||
m.Repositories["dummy"] = DummyRepository()
|
m.Repository = DummyRepository()
|
||||||
m.TargetPath = "/var/tmp/"
|
m.TargetPath = "/var/tmp/"
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func DummyRepository() *Repository {
|
func DummyRepository() *Repository {
|
||||||
// TODO(howell): handle this error
|
|
||||||
//nolint: errcheck
|
|
||||||
parsedUrl, _ := url.Parse("http://dummy.url.com")
|
|
||||||
return &Repository{
|
return &Repository{
|
||||||
Url: parsedUrl,
|
URLString: "http://dummy.url.com",
|
||||||
Username: "dummy_user",
|
CheckoutOptions: &RepoCheckout{
|
||||||
TargetPath: "dummy_targetpath",
|
Tag: "v1.0.1",
|
||||||
|
},
|
||||||
|
Auth: &RepoAuth{
|
||||||
|
Type: "ssh-key",
|
||||||
|
KeyPath: "testdata/test-key.pem",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DummyRepoAuth() *RepoAuth {
|
||||||
|
return &RepoAuth{
|
||||||
|
Type: "ssh-key",
|
||||||
|
KeyPath: "testdata/test-key.pem",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DummyRepoCheckout() *RepoCheckout {
|
||||||
|
return &RepoCheckout{
|
||||||
|
Tag: "v1.0.1",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
23
pkg/config/testdata/config-string.yaml
vendored
23
pkg/config/testdata/config-string.yaml
vendored
@ -16,20 +16,15 @@ current-context: dummy_context
|
|||||||
kind: Config
|
kind: Config
|
||||||
manifests:
|
manifests:
|
||||||
dummy_manifest:
|
dummy_manifest:
|
||||||
repositories:
|
repository:
|
||||||
dummy:
|
auth:
|
||||||
target-path: dummy_targetpath
|
ssh-key: testdata/test-key.pem
|
||||||
url:
|
type: ssh-key
|
||||||
ForceQuery: false
|
checkout:
|
||||||
Fragment: ""
|
branch: ""
|
||||||
Host: dummy.url.com
|
remote-ref: ""
|
||||||
Opaque: ""
|
tag: v1.0.1
|
||||||
Path: ""
|
url: http://dummy.url.com
|
||||||
RawPath: ""
|
|
||||||
RawQuery: ""
|
|
||||||
Scheme: http
|
|
||||||
User: null
|
|
||||||
username: dummy_user
|
|
||||||
target-path: /var/tmp/
|
target-path: /var/tmp/
|
||||||
modules-config:
|
modules-config:
|
||||||
bootstrapInfo:
|
bootstrapInfo:
|
||||||
|
23
pkg/config/testdata/manifest-string.yaml
vendored
23
pkg/config/testdata/manifest-string.yaml
vendored
@ -1,15 +1,10 @@
|
|||||||
repositories:
|
repository:
|
||||||
dummy:
|
auth:
|
||||||
target-path: dummy_targetpath
|
ssh-key: testdata/test-key.pem
|
||||||
url:
|
type: ssh-key
|
||||||
ForceQuery: false
|
checkout:
|
||||||
Fragment: ""
|
branch: ""
|
||||||
Host: dummy.url.com
|
remote-ref: ""
|
||||||
Opaque: ""
|
tag: v1.0.1
|
||||||
Path: ""
|
url: http://dummy.url.com
|
||||||
RawPath: ""
|
|
||||||
RawQuery: ""
|
|
||||||
Scheme: http
|
|
||||||
User: null
|
|
||||||
username: dummy_user
|
|
||||||
target-path: /var/tmp/
|
target-path: /var/tmp/
|
||||||
|
2
pkg/config/testdata/repo-auth-string.yaml
vendored
Normal file
2
pkg/config/testdata/repo-auth-string.yaml
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
ssh-key: testdata/test-key.pem
|
||||||
|
type: ssh-key
|
3
pkg/config/testdata/repo-checkout-string.yaml
vendored
Normal file
3
pkg/config/testdata/repo-checkout-string.yaml
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
branch: ""
|
||||||
|
remote-ref: ""
|
||||||
|
tag: v1.0.1
|
20
pkg/config/testdata/repository-string.yaml
vendored
20
pkg/config/testdata/repository-string.yaml
vendored
@ -1,12 +1,8 @@
|
|||||||
target-path: dummy_targetpath
|
auth:
|
||||||
url:
|
ssh-key: testdata/test-key.pem
|
||||||
ForceQuery: false
|
type: ssh-key
|
||||||
Fragment: ""
|
checkout:
|
||||||
Host: dummy.url.com
|
branch: ""
|
||||||
Opaque: ""
|
remote-ref: ""
|
||||||
Path: ""
|
tag: v1.0.1
|
||||||
RawPath: ""
|
url: http://dummy.url.com
|
||||||
RawQuery: ""
|
|
||||||
Scheme: http
|
|
||||||
User: null
|
|
||||||
username: dummy_user
|
|
||||||
|
28
pkg/config/testdata/test-key.pem
vendored
Normal file
28
pkg/config/testdata/test-key.pem
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||||
|
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
|
||||||
|
JjaXMuc2JjLmNvbQEC
|
||||||
|
-----END OPENSSH PRIVATE KEY-----
|
@ -17,8 +17,6 @@ limitations under the License.
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/url"
|
|
||||||
|
|
||||||
kubeconfig "k8s.io/client-go/tools/clientcmd/api"
|
kubeconfig "k8s.io/client-go/tools/clientcmd/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -119,9 +117,10 @@ type AuthInfo struct {
|
|||||||
// find the yaml manifests that airship uses to perform its operations)
|
// find the yaml manifests that airship uses to perform its operations)
|
||||||
type Manifest struct {
|
type Manifest struct {
|
||||||
// Repositories is the map of repository adddressable by a name
|
// Repositories is the map of repository adddressable by a name
|
||||||
Repositories map[string]*Repository `json:"repositories"`
|
Repository *Repository `json:"repository"`
|
||||||
|
// ExtraRepositories is the map of extra repositories addressable by a name
|
||||||
// Local Target path for working or home directory for all Manifest Cloned/Returned/Generated
|
ExtraRepositories map[string]*Repository `json:"extra-repositories,omitempty"`
|
||||||
|
// TargetPath Local Target path for working or home dirctory for all Manifest Cloned/Returned/Generated
|
||||||
TargetPath string `json:"target-path"`
|
TargetPath string `json:"target-path"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,16 +128,45 @@ type Manifest struct {
|
|||||||
// Information such as location, authentication info,
|
// Information such as location, authentication info,
|
||||||
// as well as details of what to get such as branch, tag, commit it, etc.
|
// as well as details of what to get such as branch, tag, commit it, etc.
|
||||||
type Repository struct {
|
type Repository struct {
|
||||||
// URL for Repository
|
// URLString for Repository
|
||||||
Url *url.URL `json:"url"`
|
URLString string `json:"url"`
|
||||||
|
// Auth holds authentication options against remote
|
||||||
|
Auth *RepoAuth `json:"auth,omitempty"`
|
||||||
|
// CheckoutOptions holds options to checkout repository
|
||||||
|
CheckoutOptions *RepoCheckout `json:"checkout,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// Username is the username for authentication to the repository .
|
// RepoAuth struct describes method of authentication agaist given repository
|
||||||
// +optional
|
type RepoAuth struct {
|
||||||
|
// Type of authentication method to be used with given repository
|
||||||
|
// supported types are "ssh-key", "ssh-pass", "http-basic"
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
//KeyPassword is a password decrypt ssh private key (used with ssh-key auth type)
|
||||||
|
KeyPassword string `json:"key-pass,omitempty"`
|
||||||
|
// KeyPath is path to private ssh key on disk (used with ssh-key auth type)
|
||||||
|
KeyPath string `json:"ssh-key,omitempty"`
|
||||||
|
//HTTPPassword is password for basic http authentication (used with http-basic auth type)
|
||||||
|
HTTPPassword string `json:"http-pass,omitempty"`
|
||||||
|
// SSHPassword is password for ssh password authentication (used with ssh-pass)
|
||||||
|
SSHPassword string `json:"ssh-pass,omitempty"`
|
||||||
|
// Username to authenticate against git remote (used with any type)
|
||||||
Username string `json:"username,omitempty"`
|
Username string `json:"username,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// Clone To Name Should always be relative to the setting of Manifest TargetPath.
|
// RepoCheckout container holds information how to checkout repository
|
||||||
// Defines where ths repo will be cloned to locally.
|
// Each field is mutually exclusive
|
||||||
TargetPath string `json:"target-path"`
|
type RepoCheckout struct {
|
||||||
|
// CommitHash is full hash of the commit that will be used to checkout
|
||||||
|
CommitHash string `json:"commit-hash,omitempty"`
|
||||||
|
// Branch is the branch name to checkout
|
||||||
|
Branch string `json:"branch"`
|
||||||
|
// Tag is the tag name to checkout
|
||||||
|
Tag string `json:"tag"`
|
||||||
|
// RemoteRef is not supported currently TODO
|
||||||
|
// RemoteRef is used for remote checkouts such as gerrit change requests/github pull request
|
||||||
|
// for example refs/changes/04/691202/5
|
||||||
|
// TODO Add support for fetching remote refs
|
||||||
|
RemoteRef string `json:"remote-ref"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Holds the complex cluster name information
|
// Holds the complex cluster name information
|
||||||
|
@ -43,7 +43,8 @@ func NewCluster() *Cluster {
|
|||||||
// object with non-nil maps
|
// object with non-nil maps
|
||||||
func NewManifest() *Manifest {
|
func NewManifest() *Manifest {
|
||||||
return &Manifest{
|
return &Manifest{
|
||||||
Repositories: make(map[string]*Repository),
|
Repository: NewRepository(),
|
||||||
|
ExtraRepositories: make(map[string]*Repository),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user