Skip to content

Commit ce6cb2e

Browse files
committed
Merge branch 'unit-test/scm-test' into 'master'
source code manager unit-test See merge request !122
2 parents fd1b6ad + f9698f8 commit ce6cb2e

File tree

11 files changed

+487
-152
lines changed

11 files changed

+487
-152
lines changed

cluster/calcium/build_image_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717
func TestGetRandomNode(t *testing.T) {
1818
store := &mockstore.MockStore{}
1919
config := types.Config{}
20-
c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config)}
20+
c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config.Git)}
2121

2222
n1 := &types.Node{Name: "node1", Podname: "podname", Endpoint: "tcp://10.0.0.1:2376", CPU: types.CPUMap{"0": 10, "1": 10}, Available: true}
2323
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) {
3434
func TestGetRandomNodeFail(t *testing.T) {
3535
store := &mockstore.MockStore{}
3636
config := types.Config{}
37-
c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config)}
37+
c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config.Git)}
3838

3939
n1 := &types.Node{Name: "node1", Podname: "podname", Endpoint: "tcp://10.0.0.1:2376", CPU: types.CPUMap{"0": 10, "1": 10}, Available: false}
4040
n2 := &types.Node{Name: "node2", Podname: "podname", Endpoint: "tcp://10.0.0.2:2376", CPU: types.CPUMap{"0": 10, "1": 10}, Available: false}

cluster/calcium/cluster.go

+23-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package calcium
22

33
import (
4+
"fmt"
5+
"strings"
6+
47
"gitlab.ricebook.net/platform/core/network"
58
"gitlab.ricebook.net/platform/core/network/calico"
69
"gitlab.ricebook.net/platform/core/scheduler"
710
"gitlab.ricebook.net/platform/core/scheduler/complex"
811
"gitlab.ricebook.net/platform/core/source"
12+
"gitlab.ricebook.net/platform/core/source/github"
913
"gitlab.ricebook.net/platform/core/source/gitlab"
1014
"gitlab.ricebook.net/platform/core/store"
1115
"gitlab.ricebook.net/platform/core/store/etcd"
@@ -25,6 +29,12 @@ const (
2529
BEFORE_STOP = "before_stop"
2630
)
2731

32+
const (
33+
GITLAB = "gitlab"
34+
GITHUB = "github"
35+
)
36+
37+
// New returns a new cluster config
2838
func New(config types.Config) (*calcium, error) {
2939
var err error
3040
store, err := etcdstore.New(config)
@@ -37,9 +47,20 @@ func New(config types.Config) (*calcium, error) {
3747
return nil, err
3848
}
3949
titanium := calico.New()
40-
source := gitlab.New(config)
4150

42-
return &calcium{store: store, config: config, scheduler: scheduler, network: titanium, source: source}, nil
51+
var scm source.Source
52+
scmtype := strings.ToLower(config.Git.SCMType)
53+
54+
switch scmtype {
55+
case GITLAB:
56+
scm = gitlab.New(config.Git)
57+
case GITHUB:
58+
scm = github.New(config.Git)
59+
default:
60+
return nil, fmt.Errorf("Unkonwn SCM type: %s", config.Git.SCMType)
61+
}
62+
63+
return &calcium{store: store, config: config, scheduler: scheduler, network: titanium, source: scm}, nil
4364
}
4465

4566
func (c *calcium) ResetSotre(s store.Store) {

cluster/calcium/meta_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
func TestListPods(t *testing.T) {
1616
store := &mockstore.MockStore{}
1717
config := types.Config{}
18-
c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config)}
18+
c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config.Git)}
1919

2020
store.On("GetAllPods").Return([]*types.Pod{
2121
&types.Pod{Name: "pod1", Desc: "desc1"},
@@ -36,7 +36,7 @@ func TestListPods(t *testing.T) {
3636
func TestAddPod(t *testing.T) {
3737
store := &mockstore.MockStore{}
3838
config := types.Config{}
39-
c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config)}
39+
c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config.Git)}
4040

4141
store.On("AddPod", "pod1", "desc1").Return(&types.Pod{Name: "pod1", Desc: "desc1"}, nil)
4242
store.On("AddPod", "pod2", "desc2").Return(nil, fmt.Errorf("Etcd Error"))
@@ -54,7 +54,7 @@ func TestAddPod(t *testing.T) {
5454
func TestGetPods(t *testing.T) {
5555
store := &mockstore.MockStore{}
5656
config := types.Config{}
57-
c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config)}
57+
c := &calcium{store: store, config: config, scheduler: simplescheduler.New(), network: calico.New(), source: gitlab.New(config.Git)}
5858

5959
store.On("GetPod", "pod1").Return(&types.Pod{Name: "pod1", Desc: "desc1"}, nil).Once()
6060
store.On("GetPod", "pod2").Return(nil, fmt.Errorf("Not found")).Once()

rpc/rpc_test.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,9 @@ func initConfig(mStore *mockstore.MockStore) (types.Config, *vibranium) {
198198
Zone: "c1", // zone for core, e.g. C1, C2
199199
RunAndWaitTimeout: 1200, // timeout for run and wait
200200

201-
Git: types.GitConfig{},
201+
Git: types.GitConfig{
202+
SCMType: "gitlab",
203+
},
202204
Scheduler: types.SchedConfig{
203205
LockKey: "_scheduler_lock",
204206
LockTTL: 10,

source/common/common.go

+213
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
package common
2+
3+
import (
4+
"archive/zip"
5+
"bytes"
6+
"fmt"
7+
"io"
8+
"io/ioutil"
9+
"net/http"
10+
"os"
11+
"path/filepath"
12+
"strings"
13+
14+
log "github.com/Sirupsen/logrus"
15+
"gitlab.ricebook.net/platform/core/types"
16+
git "gopkg.in/libgit2/git2go.v25"
17+
)
18+
19+
// GitScm is gitlab or github source code manager
20+
type GitScm struct {
21+
http.Client
22+
Config types.GitConfig
23+
AuthHeaders map[string]string
24+
}
25+
26+
func certificateCheckCallback(cert *git.Certificate, valid bool, hostname string) git.ErrorCode {
27+
return git.ErrorCode(0)
28+
}
29+
30+
func gitcheck(repository, pubkey, prikey string) error {
31+
if !strings.HasPrefix(repository, "git@") {
32+
return fmt.Errorf("Only support ssh protocol(%q), use git@... ", repository)
33+
}
34+
if _, err := os.Stat(pubkey); os.IsNotExist(err) {
35+
return fmt.Errorf("Public Key not found(%q)", pubkey)
36+
}
37+
if _, err := os.Stat(prikey); os.IsNotExist(err) {
38+
return fmt.Errorf("Private Key not found(%q)", prikey)
39+
}
40+
41+
return nil
42+
}
43+
44+
// SourceCode clone code from repository into path, by revision
45+
func (g *GitScm) SourceCode(repository, path, revision string) error {
46+
pubkey := g.Config.PublicKey
47+
prikey := g.Config.PrivateKey
48+
49+
if err := gitcheck(repository, pubkey, prikey); err != nil {
50+
return err
51+
}
52+
53+
credentialsCallback := func(url, username string, allowedTypes git.CredType) (git.ErrorCode, *git.Cred) {
54+
ret, cred := git.NewCredSshKey("git", pubkey, prikey, "")
55+
return git.ErrorCode(ret), &cred
56+
}
57+
58+
cloneOpts := &git.CloneOptions{
59+
FetchOptions: &git.FetchOptions{
60+
RemoteCallbacks: git.RemoteCallbacks{
61+
CredentialsCallback: credentialsCallback,
62+
CertificateCheckCallback: certificateCheckCallback,
63+
},
64+
},
65+
}
66+
67+
repo, err := git.Clone(repository, path, cloneOpts)
68+
if err != nil {
69+
log.Errorf("Error during Clone: %v", err.Error())
70+
return err
71+
}
72+
73+
if err := repo.CheckoutHead(nil); err != nil {
74+
log.Errorf("Error during CheckoutHead: %v", err.Error())
75+
return err
76+
}
77+
78+
object, err := repo.RevparseSingle(revision)
79+
if err != nil {
80+
log.Errorf("Error during RevparseSingle: %v", err.Error())
81+
return err
82+
}
83+
defer object.Free()
84+
commit, err := object.AsCommit()
85+
86+
return repo.ResetToCommit(commit, git.ResetHard, &git.CheckoutOpts{Strategy: git.CheckoutSafe})
87+
}
88+
89+
// Artifact download the artifact to the path, then unzip it
90+
func (g *GitScm) Artifact(artifact, path string) error {
91+
req, err := http.NewRequest("GET", artifact, nil)
92+
if err != nil {
93+
return err
94+
}
95+
96+
for k, v := range g.AuthHeaders {
97+
req.Header.Add(k, v)
98+
}
99+
100+
log.Debugf("Downloading artifacts from %q", artifact)
101+
resp, err := g.Do(req)
102+
if err != nil {
103+
return err
104+
}
105+
defer resp.Body.Close()
106+
if resp.StatusCode != 200 {
107+
return fmt.Errorf("Download artifact error %q", artifact)
108+
}
109+
log.Debugf("Download artifacts from %q finished", artifact)
110+
111+
// extract files from zipfile
112+
log.Debugf("Extracting files from %q", artifact)
113+
if err := UnzipFile(resp.Body, path); err != nil {
114+
return err
115+
}
116+
log.Debugf("Extraction from %q done", artifact)
117+
118+
return nil
119+
}
120+
121+
// UnzipFile unzip a file(from resp.Body) to the spec path
122+
func UnzipFile(body io.ReadCloser, path string) error {
123+
content, err := ioutil.ReadAll(body)
124+
if err != nil {
125+
return err
126+
}
127+
128+
reader, err := zip.NewReader(bytes.NewReader(content), int64(len(content)))
129+
if err != nil {
130+
return err
131+
}
132+
133+
// extract files from zipfile
134+
for _, f := range reader.File {
135+
zipped, err := f.Open()
136+
if err != nil {
137+
return err
138+
}
139+
140+
defer zipped.Close()
141+
142+
p := filepath.Join(path, f.Name)
143+
144+
if f.FileInfo().IsDir() {
145+
os.MkdirAll(p, f.Mode())
146+
continue
147+
}
148+
149+
writer, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE, f.Mode())
150+
if err != nil {
151+
return err
152+
}
153+
154+
defer writer.Close()
155+
if _, err = io.Copy(writer, zipped); err != nil {
156+
return err
157+
}
158+
}
159+
return nil
160+
}
161+
162+
// ZipFiles compresses one or many files into a single zip archive file
163+
func ZipFiles(filename string, files []string) error {
164+
165+
newfile, err := os.Create(filename)
166+
if err != nil {
167+
return err
168+
}
169+
defer newfile.Close()
170+
171+
zipWriter := zip.NewWriter(newfile)
172+
defer zipWriter.Close()
173+
174+
// Add files to zip
175+
for _, file := range files {
176+
177+
zipfile, err := os.Open(file)
178+
if err != nil {
179+
return err
180+
}
181+
defer zipfile.Close()
182+
183+
// Get the file information
184+
info, err := zipfile.Stat()
185+
if err != nil {
186+
return err
187+
}
188+
189+
header, err := zip.FileInfoHeader(info)
190+
if err != nil {
191+
return err
192+
}
193+
194+
// Change to deflate to gain better compression
195+
// see http://golang.org/pkg/archive/zip/#pkg-constants
196+
header.Method = zip.Deflate
197+
198+
writer, err := zipWriter.CreateHeader(header)
199+
if err != nil {
200+
return err
201+
}
202+
_, err = io.Copy(writer, zipfile)
203+
if err != nil {
204+
return err
205+
}
206+
}
207+
return nil
208+
}
209+
210+
// Security remove the .git folder
211+
func (g *GitScm) Security(path string) error {
212+
return os.RemoveAll(filepath.Join(path, ".git"))
213+
}

0 commit comments

Comments
 (0)