[#13] Add document pull command

Adds `airshipctl document pull` command that will check the current
manifest specified by the config and download it to the config specified
target path.

Change-Id: I493564c056225ff1e19f5d1aecb8c187683529ec
This commit is contained in:
Ian H. Pittwood 2019-12-13 10:31:47 -06:00
parent 1399c569f4
commit 7437bb2972
14 changed files with 251 additions and 2 deletions

View File

@ -14,6 +14,7 @@ func NewDocumentCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Com
Short: "manages deployment documents", Short: "manages deployment documents",
} }
documentRootCmd.AddCommand(NewDocumentPullCommand(rootSettings))
documentRootCmd.AddCommand(secret.NewSecretCommand(rootSettings)) documentRootCmd.AddCommand(secret.NewSecretCommand(rootSettings))
return documentRootCmd return documentRootCmd

22
cmd/document/pull.go Normal file
View File

@ -0,0 +1,22 @@
package document
import (
"github.com/spf13/cobra"
"opendev.org/airship/airshipctl/pkg/document/pull"
"opendev.org/airship/airshipctl/pkg/environment"
)
// NewDocumentPullCommand creates a new command for pulling airship document repositories
func NewDocumentPullCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command {
settings := pull.Settings{AirshipCTLSettings: rootSettings}
documentPullCmd := &cobra.Command{
Use: "pull",
Short: "pulls documents from remote git repository",
RunE: func(cmd *cobra.Command, args []string) error {
return settings.Pull()
},
}
return documentPullCmd
}

47
cmd/document/pull_test.go Normal file
View File

@ -0,0 +1,47 @@
package document
import (
"testing"
"opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/environment"
"opendev.org/airship/airshipctl/testutil"
)
func getDummyAirshipSettings() *environment.AirshipCTLSettings {
settings := new(environment.AirshipCTLSettings)
conf := config.DummyConfig()
mfst := conf.Manifests["dummy_manifest"]
mfst.Repository = &config.Repository{
URLString: "https://opendev.org/airship/treasuremap.git",
CheckoutOptions: &config.RepoCheckout{
Branch: "master",
ForceCheckout: false,
},
Auth: &config.RepoAuth{
Type: "http-basic",
},
}
settings.SetConfig(conf)
return settings
}
func TestPull(t *testing.T) {
cmdTests := []*testutil.CmdTest{
{
Name: "document-pull-cmd-with-defaults",
CmdLine: "",
Cmd: NewDocumentPullCommand(getDummyAirshipSettings()),
},
{
Name: "document-pull-cmd-with-help",
CmdLine: "--help",
Cmd: NewDocumentPullCommand(nil),
},
}
for _, tt := range cmdTests {
testutil.RunTest(t, tt)
}
}

View File

@ -0,0 +1,7 @@
pulls documents from remote git repository
Usage:
pull [flags]
Flags:
-h, --help help for pull

1
go.sum
View File

@ -536,6 +536,7 @@ golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a h1:mEQZbbaBjWyLNy0tmZmgEuQAR8XOQ3hL8GYi3J/NG64=
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=

View File

@ -94,7 +94,8 @@ func DummyRepository() *Repository {
return &Repository{ return &Repository{
URLString: "http://dummy.url.com", URLString: "http://dummy.url.com",
CheckoutOptions: &RepoCheckout{ CheckoutOptions: &RepoCheckout{
Tag: "v1.0.1", Tag: "v1.0.1",
ForceCheckout: false,
}, },
Auth: &RepoAuth{ Auth: &RepoAuth{
Type: "ssh-key", Type: "ssh-key",
@ -112,7 +113,8 @@ func DummyRepoAuth() *RepoAuth {
func DummyRepoCheckout() *RepoCheckout { func DummyRepoCheckout() *RepoCheckout {
return &RepoCheckout{ return &RepoCheckout{
Tag: "v1.0.1", Tag: "v1.0.1",
ForceCheckout: false,
} }
} }

View File

@ -22,6 +22,7 @@ manifests:
type: ssh-key type: ssh-key
checkout: checkout:
branch: "" branch: ""
force: false
remote-ref: "" remote-ref: ""
tag: v1.0.1 tag: v1.0.1
url: http://dummy.url.com url: http://dummy.url.com

View File

@ -4,6 +4,7 @@ repository:
type: ssh-key type: ssh-key
checkout: checkout:
branch: "" branch: ""
force: false
remote-ref: "" remote-ref: ""
tag: v1.0.1 tag: v1.0.1
url: http://dummy.url.com url: http://dummy.url.com

View File

@ -1,3 +1,4 @@
branch: "" branch: ""
force: false
remote-ref: "" remote-ref: ""
tag: v1.0.1 tag: v1.0.1

View File

@ -3,6 +3,7 @@ auth:
type: ssh-key type: ssh-key
checkout: checkout:
branch: "" branch: ""
force: false
remote-ref: "" remote-ref: ""
tag: v1.0.1 tag: v1.0.1
url: http://dummy.url.com url: http://dummy.url.com

View File

@ -167,6 +167,8 @@ type RepoCheckout struct {
// for example refs/changes/04/691202/5 // for example refs/changes/04/691202/5
// TODO Add support for fetching remote refs // TODO Add support for fetching remote refs
RemoteRef string `json:"remote-ref"` RemoteRef string `json:"remote-ref"`
// ForceCheckout is a boolean to indicate whether to use the `--force` option when checking out
ForceCheckout bool `json:"force"`
} }
// Holds the complex cluster name information // Holds the complex cluster name information

53
pkg/document/pull/pull.go Normal file
View File

@ -0,0 +1,53 @@
package pull
import (
"opendev.org/airship/airshipctl/pkg/document/repo"
"opendev.org/airship/airshipctl/pkg/environment"
)
type Settings struct {
*environment.AirshipCTLSettings
}
func (s *Settings) Pull() error {
err := s.cloneRepositories()
if err != nil {
return err
}
return nil
}
func (s *Settings) cloneRepositories() error {
// Clone main repository
currentManifest, err := s.Config().CurrentContextManifest()
if err != nil {
return err
}
mainRepoConfig := currentManifest.Repository
repository, err := repo.NewRepository(currentManifest.TargetPath, mainRepoConfig)
if err != nil {
return err
}
err = repository.Download(mainRepoConfig.ToCheckoutOptions(true).Force)
if err != nil {
return err
}
repository.Driver.Close()
// Clone extra repositories
for _, extraRepoConfig := range currentManifest.ExtraRepositories {
repository, err := repo.NewRepository(currentManifest.TargetPath, extraRepoConfig)
if err != nil {
return err
}
err = repository.Download(extraRepoConfig.ToCheckoutOptions(true).Force)
if err != nil {
return err
}
repository.Driver.Close()
}
return nil
}

View File

@ -0,0 +1,110 @@
package pull
import (
"io/ioutil"
"path"
"path/filepath"
"strings"
"testing"
fixtures "gopkg.in/src-d/go-git-fixtures.v3"
repo2 "opendev.org/airship/airshipctl/pkg/document/repo"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/environment"
)
func getDummyPullSettings() *Settings {
mockPullSettings := &Settings{
AirshipCTLSettings: new(environment.AirshipCTLSettings),
}
mockConf := config.DummyConfig()
mockPullSettings.AirshipCTLSettings.SetConfig(mockConf)
return mockPullSettings
}
func TestPull(t *testing.T) {
require := require.New(t)
assert := assert.New(t)
t.Run("cloneRepositories", func(t *testing.T) {
dummyPullSettings := getDummyPullSettings()
currentManifest, err := dummyPullSettings.Config().CurrentContextManifest()
require.NoError(err)
err = fixtures.Init()
require.NoError(err)
fx := fixtures.Basic().One()
dummyGitDir := fx.DotGit().Root()
currentManifest.Repository = &config.Repository{
URLString: dummyGitDir,
CheckoutOptions: &config.RepoCheckout{
Branch: "master",
ForceCheckout: false,
},
Auth: &config.RepoAuth{
Type: "http-basic",
},
}
tmpDir, err := ioutil.TempDir("", "airshipctlPullTest-")
require.NoError(err)
currentManifest.TargetPath = tmpDir
_, err = repo2.NewRepository(".", currentManifest.Repository)
require.NoError(err)
err = dummyPullSettings.cloneRepositories()
require.NoError(err)
dummyRepoDirName := filepath.Base(dummyGitDir)
assert.FileExists(path.Join(tmpDir, dummyRepoDirName, "go/example.go"))
assert.FileExists(path.Join(tmpDir, dummyRepoDirName, ".git/HEAD"))
contents, err := ioutil.ReadFile(path.Join(tmpDir, dummyRepoDirName, ".git/HEAD"))
require.NoError(err)
assert.Equal("ref: refs/heads/master", strings.TrimRight(string(contents), "\t \n"))
})
t.Run("Pull", func(t *testing.T) {
dummyPullSettings := getDummyPullSettings()
conf := dummyPullSettings.AirshipCTLSettings.Config()
err := fixtures.Init()
require.NoError(err)
fx := fixtures.Basic().One()
mfst := conf.Manifests["dummy_manifest"]
dummyGitDir := fx.DotGit().Root()
mfst.Repository = &config.Repository{
URLString: dummyGitDir,
CheckoutOptions: &config.RepoCheckout{
Branch: "master",
ForceCheckout: false,
},
Auth: &config.RepoAuth{
Type: "http-basic",
},
}
dummyPullSettings.SetConfig(conf)
tmpDir, err := ioutil.TempDir("", "airshipctlPullTest-")
require.NoError(err)
mfst.TargetPath = tmpDir
require.NoError(err)
err = dummyPullSettings.Pull()
require.NoError(err)
dummyRepoDirName := filepath.Base(dummyGitDir)
assert.FileExists(path.Join(tmpDir, dummyRepoDirName, "go/example.go"))
assert.FileExists(path.Join(tmpDir, dummyRepoDirName, ".git/HEAD"))
contents, err := ioutil.ReadFile(path.Join(tmpDir, dummyRepoDirName, ".git/HEAD"))
require.NoError(err)
assert.Equal("ref: refs/heads/master", strings.TrimRight(string(contents), "\t \n"))
})
}