diff --git a/cluster/calcium/build_image_test.go b/cluster/calcium/build_image_test.go index 96b9aa600..3ec74e4fd 100644 --- a/cluster/calcium/build_image_test.go +++ b/cluster/calcium/build_image_test.go @@ -17,7 +17,7 @@ import ( func TestGetRandomNode(t *testing.T) { store := &mockstore.MockStore{} config := types.Config{} - c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config)} + c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config.Git)} n1 := &types.Node{Name: "node1", Podname: "podname", Endpoint: "tcp://10.0.0.1:2376", CPU: types.CPUMap{"0": 10, "1": 10}, Available: true} n2 := &types.Node{Name: "node2", Podname: "podname", Endpoint: "tcp://10.0.0.2:2376", CPU: types.CPUMap{"0": 10, "1": 10}, Available: true} @@ -34,7 +34,7 @@ func TestGetRandomNode(t *testing.T) { func TestGetRandomNodeFail(t *testing.T) { store := &mockstore.MockStore{} config := types.Config{} - c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config)} + c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config.Git)} n1 := &types.Node{Name: "node1", Podname: "podname", Endpoint: "tcp://10.0.0.1:2376", CPU: types.CPUMap{"0": 10, "1": 10}, Available: false} n2 := &types.Node{Name: "node2", Podname: "podname", Endpoint: "tcp://10.0.0.2:2376", CPU: types.CPUMap{"0": 10, "1": 10}, Available: false} diff --git a/cluster/calcium/cluster.go b/cluster/calcium/cluster.go index ca4cdcf88..9256f41f5 100644 --- a/cluster/calcium/cluster.go +++ b/cluster/calcium/cluster.go @@ -1,11 +1,15 @@ package calcium import ( + "fmt" + "strings" + "gitlab.ricebook.net/platform/core/network" "gitlab.ricebook.net/platform/core/network/calico" "gitlab.ricebook.net/platform/core/scheduler" "gitlab.ricebook.net/platform/core/scheduler/complex" "gitlab.ricebook.net/platform/core/source" + "gitlab.ricebook.net/platform/core/source/github" "gitlab.ricebook.net/platform/core/source/gitlab" "gitlab.ricebook.net/platform/core/store" "gitlab.ricebook.net/platform/core/store/etcd" @@ -25,6 +29,12 @@ const ( BEFORE_STOP = "before_stop" ) +const ( + GITLAB = "gitlab" + GITHUB = "github" +) + +// New returns a new cluster config func New(config types.Config) (*calcium, error) { var err error store, err := etcdstore.New(config) @@ -37,9 +47,20 @@ func New(config types.Config) (*calcium, error) { return nil, err } titanium := calico.New() - source := gitlab.New(config) - return &calcium{store: store, config: config, scheduler: scheduler, network: titanium, source: source}, nil + var scm source.Source + scmtype := strings.ToLower(config.Git.SCMType) + + switch scmtype { + case GITLAB: + scm = gitlab.New(config.Git) + case GITHUB: + scm = github.New(config.Git) + default: + return nil, fmt.Errorf("Unkonwn SCM type: %s", config.Git.SCMType) + } + + return &calcium{store: store, config: config, scheduler: scheduler, network: titanium, source: scm}, nil } func (c *calcium) ResetSotre(s store.Store) { diff --git a/cluster/calcium/meta_test.go b/cluster/calcium/meta_test.go index 3e38416c0..57fd802a2 100644 --- a/cluster/calcium/meta_test.go +++ b/cluster/calcium/meta_test.go @@ -15,7 +15,7 @@ import ( func TestListPods(t *testing.T) { store := &mockstore.MockStore{} config := types.Config{} - c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config)} + c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config.Git)} store.On("GetAllPods").Return([]*types.Pod{ &types.Pod{Name: "pod1", Desc: "desc1"}, @@ -36,7 +36,7 @@ func TestListPods(t *testing.T) { func TestAddPod(t *testing.T) { store := &mockstore.MockStore{} config := types.Config{} - c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config)} + c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config.Git)} store.On("AddPod", "pod1", "desc1").Return(&types.Pod{Name: "pod1", Desc: "desc1"}, nil) store.On("AddPod", "pod2", "desc2").Return(nil, fmt.Errorf("Etcd Error")) @@ -54,7 +54,7 @@ func TestAddPod(t *testing.T) { func TestGetPods(t *testing.T) { store := &mockstore.MockStore{} config := types.Config{} - c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config)} + c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config.Git)} store.On("GetPod", "pod1").Return(&types.Pod{Name: "pod1", Desc: "desc1"}, nil).Once() store.On("GetPod", "pod2").Return(nil, fmt.Errorf("Not found")).Once() diff --git a/rpc/rpc_test.go b/rpc/rpc_test.go index 787303c92..8d78fb36a 100644 --- a/rpc/rpc_test.go +++ b/rpc/rpc_test.go @@ -198,7 +198,9 @@ func initConfig(mStore *mockstore.MockStore) (types.Config, *vibranium) { Zone: "c1", // zone for core, e.g. C1, C2 RunAndWaitTimeout: 1200, // timeout for run and wait - Git: types.GitConfig{}, + Git: types.GitConfig{ + SCMType: "gitlab", + }, Scheduler: types.SchedConfig{ LockKey: "_scheduler_lock", LockTTL: 10, diff --git a/source/common/common.go b/source/common/common.go new file mode 100644 index 000000000..ceaa5e226 --- /dev/null +++ b/source/common/common.go @@ -0,0 +1,213 @@ +package common + +import ( + "archive/zip" + "bytes" + "fmt" + "io" + "io/ioutil" + "net/http" + "os" + "path/filepath" + "strings" + + log "github.com/Sirupsen/logrus" + "gitlab.ricebook.net/platform/core/types" + git "gopkg.in/libgit2/git2go.v25" +) + +// GitScm is gitlab or github source code manager +type GitScm struct { + http.Client + Config types.GitConfig + AuthHeaders map[string]string +} + +func certificateCheckCallback(cert *git.Certificate, valid bool, hostname string) git.ErrorCode { + return git.ErrorCode(0) +} + +func gitcheck(repository, pubkey, prikey string) error { + if !strings.HasPrefix(repository, "git@") { + return fmt.Errorf("Only support ssh protocol(%q), use git@... ", repository) + } + if _, err := os.Stat(pubkey); os.IsNotExist(err) { + return fmt.Errorf("Public Key not found(%q)", pubkey) + } + if _, err := os.Stat(prikey); os.IsNotExist(err) { + return fmt.Errorf("Private Key not found(%q)", prikey) + } + + return nil +} + +// SourceCode clone code from repository into path, by revision +func (g *GitScm) SourceCode(repository, path, revision string) error { + pubkey := g.Config.PublicKey + prikey := g.Config.PrivateKey + + if err := gitcheck(repository, pubkey, prikey); err != nil { + return err + } + + credentialsCallback := func(url, username string, allowedTypes git.CredType) (git.ErrorCode, *git.Cred) { + ret, cred := git.NewCredSshKey("git", pubkey, prikey, "") + return git.ErrorCode(ret), &cred + } + + cloneOpts := &git.CloneOptions{ + FetchOptions: &git.FetchOptions{ + RemoteCallbacks: git.RemoteCallbacks{ + CredentialsCallback: credentialsCallback, + CertificateCheckCallback: certificateCheckCallback, + }, + }, + } + + repo, err := git.Clone(repository, path, cloneOpts) + if err != nil { + log.Errorf("Error during Clone: %v", err.Error()) + return err + } + + if err := repo.CheckoutHead(nil); err != nil { + log.Errorf("Error during CheckoutHead: %v", err.Error()) + return err + } + + object, err := repo.RevparseSingle(revision) + if err != nil { + log.Errorf("Error during RevparseSingle: %v", err.Error()) + return err + } + defer object.Free() + commit, err := object.AsCommit() + + return repo.ResetToCommit(commit, git.ResetHard, &git.CheckoutOpts{Strategy: git.CheckoutSafe}) +} + +// Artifact download the artifact to the path, then unzip it +func (g *GitScm) Artifact(artifact, path string) error { + req, err := http.NewRequest("GET", artifact, nil) + if err != nil { + return err + } + + for k, v := range g.AuthHeaders { + req.Header.Add(k, v) + } + + log.Debugf("Downloading artifacts from %q", artifact) + resp, err := g.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + if resp.StatusCode != 200 { + return fmt.Errorf("Download artifact error %q", artifact) + } + log.Debugf("Download artifacts from %q finished", artifact) + + // extract files from zipfile + log.Debugf("Extracting files from %q", artifact) + if err := UnzipFile(resp.Body, path); err != nil { + return err + } + log.Debugf("Extraction from %q done", artifact) + + return nil +} + +// UnzipFile unzip a file(from resp.Body) to the spec path +func UnzipFile(body io.ReadCloser, path string) error { + content, err := ioutil.ReadAll(body) + if err != nil { + return err + } + + reader, err := zip.NewReader(bytes.NewReader(content), int64(len(content))) + if err != nil { + return err + } + + // extract files from zipfile + for _, f := range reader.File { + zipped, err := f.Open() + if err != nil { + return err + } + + defer zipped.Close() + + p := filepath.Join(path, f.Name) + + if f.FileInfo().IsDir() { + os.MkdirAll(p, f.Mode()) + continue + } + + writer, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE, f.Mode()) + if err != nil { + return err + } + + defer writer.Close() + if _, err = io.Copy(writer, zipped); err != nil { + return err + } + } + return nil +} + +// ZipFiles compresses one or many files into a single zip archive file +func ZipFiles(filename string, files []string) error { + + newfile, err := os.Create(filename) + if err != nil { + return err + } + defer newfile.Close() + + zipWriter := zip.NewWriter(newfile) + defer zipWriter.Close() + + // Add files to zip + for _, file := range files { + + zipfile, err := os.Open(file) + if err != nil { + return err + } + defer zipfile.Close() + + // Get the file information + info, err := zipfile.Stat() + if err != nil { + return err + } + + header, err := zip.FileInfoHeader(info) + if err != nil { + return err + } + + // Change to deflate to gain better compression + // see http://golang.org/pkg/archive/zip/#pkg-constants + header.Method = zip.Deflate + + writer, err := zipWriter.CreateHeader(header) + if err != nil { + return err + } + _, err = io.Copy(writer, zipfile) + if err != nil { + return err + } + } + return nil +} + +// Security remove the .git folder +func (g *GitScm) Security(path string) error { + return os.RemoveAll(filepath.Join(path, ".git")) +} diff --git a/source/common/common_test.go b/source/common/common_test.go new file mode 100644 index 000000000..c736b3f61 --- /dev/null +++ b/source/common/common_test.go @@ -0,0 +1,83 @@ +package common + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "gitlab.ricebook.net/platform/core/types" +) + +// Since normal tests were tested in `source_test.go`, only test errors here. + +var ( + repo = "git@github.com:noexist/noexist.git" + revision = "bye" + config = types.GitConfig{} + artifactURL = "https://enjoy.ricebook.com/" +) + +func initTest() { + pubkeyPath, _ := ioutil.TempFile(os.TempDir(), "pubkey-") + pubkeyPath.WriteString("") + defer pubkeyPath.Close() + + prikeyPath, _ := ioutil.TempFile(os.TempDir(), "prikey-") + prikeyPath.WriteString("") + defer prikeyPath.Close() + + config = types.GitConfig{ + PublicKey: pubkeyPath.Name(), + PrivateKey: prikeyPath.Name(), + Token: "token", + } +} + +func TestSourceCode(t *testing.T) { + initTest() + source := GitScm{Config: config} + + defer os.RemoveAll(config.PublicKey) + defer os.RemoveAll(config.PrivateKey) + + path, err := ioutil.TempDir(os.TempDir(), "sourcecode-") + if err != nil { + t.Error(err) + } + defer os.RemoveAll(path) + + // empty key + err = source.SourceCode(repo, path, revision) + assert.Error(t, err) + assert.Contains(t, err.Error(), "Failed to authenticate SSH session") + + // key not found + source.Config.PrivateKey = "" + err = source.SourceCode(repo, path, revision) + assert.Error(t, err) + assert.Contains(t, err.Error(), "Private Key not found") + + // use https protocol + repo = "https://github.com/hello/word.git" + err = source.SourceCode(repo, path, revision) + assert.Error(t, err) + assert.Contains(t, err.Error(), "Only support ssh protocol") +} + +func TestGitLabArtifact(t *testing.T) { + initTest() + source := GitScm{Config: config} + + defer os.Remove(config.PublicKey) + defer os.Remove(config.PrivateKey) + + err := source.Artifact(artifactURL, "") + assert.Error(t, err) + assert.Contains(t, err.Error(), "zip: not a valid zip file") + + artifactURL = "http://localhost:0" + err = source.Artifact(artifactURL, "") + assert.Error(t, err) + assert.Contains(t, err.Error(), "connection refused") +} diff --git a/source/github/manganese.go b/source/github/manganese.go new file mode 100644 index 000000000..131b53afa --- /dev/null +++ b/source/github/manganese.go @@ -0,0 +1,15 @@ +package github + +import ( + "fmt" + + "gitlab.ricebook.net/platform/core/source/common" + "gitlab.ricebook.net/platform/core/types" +) + +func New(config types.GitConfig) *common.GitScm { + token := fmt.Sprintf("token %s", config.Token) + authheaders := map[string]string{} + authheaders["Authorization"] = token + return &common.GitScm{Config: config, AuthHeaders: authheaders} +} diff --git a/source/gitlab/cesium.go b/source/gitlab/cesium.go index ebedc2e4a..fc7935ae7 100644 --- a/source/gitlab/cesium.go +++ b/source/gitlab/cesium.go @@ -1,148 +1,12 @@ package gitlab import ( - "archive/zip" - "bytes" - "fmt" - "io" - "io/ioutil" - "net/http" - "os" - "path/filepath" - "strings" - - log "github.com/Sirupsen/logrus" + "gitlab.ricebook.net/platform/core/source/common" "gitlab.ricebook.net/platform/core/types" - "gopkg.in/libgit2/git2go.v25" ) -type cesium struct { - http.Client - config types.Config -} - -const gitUser = "git" - -func certificateCheckCallback(cert *git.Certificate, valid bool, hostname string) git.ErrorCode { - return git.ErrorCode(0) -} - -// clone code from repository into path, by revision -func (c *cesium) SourceCode(repository, path, revision string) error { - pubkey := c.config.Git.PublicKey - prikey := c.config.Git.PrivateKey - - if !strings.HasPrefix(repository, "git@") { - return fmt.Errorf("Only support ssh protocol(%q), use git@...", repository) - } - if _, err := os.Stat(pubkey); os.IsNotExist(err) { - return fmt.Errorf("Public Key not found(%q)", pubkey) - } - if _, err := os.Stat(prikey); os.IsNotExist(err) { - return fmt.Errorf("Private Key not found(%q)", prikey) - } - - credentialsCallback := func(url, username string, allowedTypes git.CredType) (git.ErrorCode, *git.Cred) { - ret, cred := git.NewCredSshKey(gitUser, pubkey, prikey, "") - return git.ErrorCode(ret), &cred - } - - cloneOpts := &git.CloneOptions{ - FetchOptions: &git.FetchOptions{ - RemoteCallbacks: git.RemoteCallbacks{ - CredentialsCallback: credentialsCallback, - CertificateCheckCallback: certificateCheckCallback, - }, - }, - } - - repo, err := git.Clone(repository, path, cloneOpts) - if err != nil { - log.Errorf("Error during Clone: %v", err.Error()) - return err - } - - if err := repo.CheckoutHead(nil); err != nil { - log.Errorf("Error during CheckoutHead: %v", err.Error()) - return err - } - - object, err := repo.RevparseSingle(revision) - if err != nil { - log.Errorf("Error during RevparseSingle: %v", err.Error()) - return err - } - defer object.Free() - commit, err := object.AsCommit() - - return repo.ResetToCommit(commit, git.ResetHard, &git.CheckoutOpts{Strategy: git.CheckoutSafe}) -} - -// Download artifact to path, and unzip it -// artifact is like "http://gitlab.ricebook.net/api/v3/projects/:project_id/builds/:build_id/artifacts" -func (c *cesium) Artifact(artifact, path string) error { - req, err := http.NewRequest("GET", artifact, nil) - if err != nil { - return err - } - - req.Header.Add("PRIVATE-TOKEN", c.config.Git.GitlabToken) - resp, err := c.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - if resp.StatusCode != 200 { - return fmt.Errorf("Download artifact error %q", artifact) - } - - log.Debugf("Downloading artifacts from %q", artifact) - content, err := ioutil.ReadAll(resp.Body) - if err != nil { - return err - } - - log.Debugf("Extracting files from %q", artifact) - reader, err := zip.NewReader(bytes.NewReader(content), int64(len(content))) - if err != nil { - return err - } - - // extract files from zipfile - for _, f := range reader.File { - zipped, err := f.Open() - if err != nil { - return err - } - - defer zipped.Close() - - p := filepath.Join(path, f.Name) - - if f.FileInfo().IsDir() { - os.MkdirAll(p, f.Mode()) - continue - } - - writer, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE, f.Mode()) - if err != nil { - return err - } - - defer writer.Close() - if _, err = io.Copy(writer, zipped); err != nil { - return err - } - } - log.Debugf("Extraction from %q done", artifact) - return nil -} - -func (c *cesium) Security(path string) error { - return os.RemoveAll(filepath.Join(path, ".git")) -} - -func New(config types.Config) *cesium { - return &cesium{config: config} +func New(config types.GitConfig) *common.GitScm { + authheaders := map[string]string{} + authheaders["PRIVATE-TOKEN"] = config.Token + return &common.GitScm{Config: config, AuthHeaders: authheaders} } diff --git a/source/source.go b/source/source.go index d257ef993..3d53305ee 100644 --- a/source/source.go +++ b/source/source.go @@ -1,5 +1,6 @@ package source +// Source defines SCM funcions type Source interface { // Get source code from repository into path by revision SourceCode(repository, path, revision string) error diff --git a/source/source_test.go b/source/source_test.go new file mode 100644 index 000000000..7972f8743 --- /dev/null +++ b/source/source_test.go @@ -0,0 +1,135 @@ +package source + +import ( + "fmt" + "io/ioutil" + "log" + "net/http" + "os" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "gitlab.ricebook.net/platform/core/source/common" + "gitlab.ricebook.net/platform/core/source/gitlab" + "gitlab.ricebook.net/platform/core/types" +) + +var ( + repo = "git@github.com:noexist/noexist.git" + revision = "6" + config = types.GitConfig{} + artifactURL = "http://127.0.0.1:8088/" +) + +const prikeyString = `-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQC4OPXmSaaTGls9gZXO+Z2CBDeeWBPPwcOMa8wdzlws3cdUKulA +5wcblHvtN2ou1xpS9emtW5Tbo2qQFyXPL6pPYwBDq+YnkpbEGC2csMkV+JdWyTw+ +4J616msS+VZ9j8Q2+calg2KL2mG504iXgCyGWu4dT9Ptplt5KWwaOsTl9wIDAQAB +AoGAZqxocHbv/eCcpYUJp5d7b7FGBlx0fkAx6ptR4fLXcLISnBhmdCPO1FJHV4ih +B4YfR8mC+XmnV1qW08Py8KxSMIVBjqFxunv2+p9RhwnP0K8Pi3OuQO1EsUMeSRwG +w2AXAgDdlBuLQB2j6ixsJsKfCdA7El7qu8WDNwozWwwacTECQQDxZfdrgOS+xDNn +Nm1bEcQySOOJH2x1d+sR8pLQT5nHs7Q9DXvBdJvMtcgPkWltmtoueap+GjrmE4uZ +qmUmDHsFAkEAw12hnE4iADSVuLAn+vYdLNebY0GdB5MSumuouXaVrzyqNgwDYk6h +2BGgxUC8LPcZePhAAZZMqRpwBpRaLotFywJBAI4glO4ss4FGD2XDe9tUuIlKtPz1 +DWyUMEke4yXW2BnmSkZv+99JAroihSn1WXd45uDaLXGVi/wOofDVjDw8uOkCQQCK +xwY4HCB2+OOqMCgWU6Hh6r6MwV0ktkrFdhiCtkQaGQPoJJx6xtScwdjshdGmN1k2 +31HITtXiAc+2PMfa7EAFAkEAtyqskXhSzLcOS0WWQnfhy0m5oA7lnlFYi7SaWAHo ++VwICwafZ3oMc+pAqHzIDb9h1wnX5O++YafDbGeiT+7QvA== +-----END RSA PRIVATE KEY-----` + +const pubkeyString = `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC4OPXmSaaTGls9gZXO+Z2CBDeeWBPPwcOMa8wdzlws3cdUKulA5wcblHvtN2ou1xpS9emtW5Tbo2qQFyXPL6pPYwBDq+YnkpbEGC2csMkV+JdWyTw+4J616msS+VZ9j8Q2+calg2KL2mG504iXgCyGWu4dT9Ptplt5KWwaOsTl9w== mr@rabbit` + +func initTest() { + pubkeyPath, _ := ioutil.TempFile(os.TempDir(), "pubkey-") + pubkeyPath.WriteString(pubkeyString) + defer pubkeyPath.Close() + + prikeyPath, _ := ioutil.TempFile(os.TempDir(), "prikey-") + prikeyPath.WriteString(prikeyString) + defer prikeyPath.Close() + + config = types.GitConfig{ + PublicKey: pubkeyPath.Name(), + PrivateKey: prikeyPath.Name(), + Token: "x", + } +} + +func TestGitSourceCode(t *testing.T) { + initTest() + source := common.GitScm{Config: config} + + defer os.RemoveAll(config.PublicKey) + defer os.RemoveAll(config.PrivateKey) + + path, err := ioutil.TempDir(os.TempDir(), "sourcecode-") + if err != nil { + t.Error(err) + } + defer os.RemoveAll(path) + + err = source.SourceCode(repo, path, revision) + assert.Error(t, err) + assert.EqualError(t, err, "Failed to authenticate SSH session: Waiting for USERAUTH response") +} + +func simpleHTTPServer(file *os.File) { + zipFile, _ := os.Open(fmt.Sprintf("%s.zip", file.Name())) + defer zipFile.Close() + + if err := common.ZipFiles(zipFile.Name(), []string{file.Name()}); err != nil { + log.Fatal(err) + return + } + + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + http.ServeFile(w, r, zipFile.Name()) + }) + + err := http.ListenAndServe(":8088", nil) + if err != nil { + log.Fatal("ListenAndServe: ", err) + } +} + +func TestGitLabArtifact(t *testing.T) { + file, _ := ioutil.TempFile(os.TempDir(), "file-") + defer file.Close() + defer os.Remove(file.Name()) + file.WriteString(prikeyString) + + zipFile, _ := os.Create(fmt.Sprintf("%s.zip", file.Name())) + defer zipFile.Close() + defer os.Remove(zipFile.Name()) + + go simpleHTTPServer(file) + // give 1s to httpServer zip the file and start up + time.Sleep(1 * time.Second) + + initTest() + source := gitlab.New(config) + + defer os.Remove(config.PublicKey) + defer os.Remove(config.PrivateKey) + + path, err := ioutil.TempDir(os.TempDir(), "sourcecode-") + if err != nil { + t.Error(err) + } + defer os.RemoveAll(path) + + err = source.Artifact(artifactURL, path) + assert.NoError(t, err) + + fileAbPath := strings.TrimPrefix(file.Name(), os.TempDir()) + downloadFilePath := fmt.Sprintf("%s%s", path, fileAbPath) + fmt.Println(downloadFilePath) + + downloadFile, err := os.Open(downloadFilePath) + assert.NoError(t, err) + artifactString, _ := ioutil.ReadAll(downloadFile) + // diff the artifact and the origin + assert.Equal(t, string(artifactString), prikeyString) +} diff --git a/types/config.go b/types/config.go index 3dd918838..dd8dcf398 100644 --- a/types/config.go +++ b/types/config.go @@ -22,9 +22,10 @@ type Config struct { // GitConfig holds eru-core git config type GitConfig struct { - PublicKey string `yaml:"public_key"` // public key to clone code - PrivateKey string `yaml:"private_key"` // private key to clone code - GitlabToken string `yaml:"gitlab_token"` // GitLab token to call GitLab API + SCMType string `yaml:"scm_type"` // source code manager type [gitlab/github] + PublicKey string `yaml:"public_key"` // public key to clone code + PrivateKey string `yaml:"private_key"` // private key to clone code + Token string `yaml:"token"` // Token to call SCM API } // DockerConfig holds eru-core docker config