* add devops client interface Signed-off-by: runzexia <runzexia@yunify.com> * direct return jenkins Signed-off-by: runzexia <runzexia@yunify.com> * add some interface Signed-off-by: runzexia <runzexia@yunify.com> * update Signed-off-by: runzexia <runzexia@yunify.com> * update interface Signed-off-by: runzexia <runzexia@yunify.com> * update Signed-off-by: runzexia <runzexia@yunify.com> * credential op structs Signed-off-by: runzexia <runzexia@yunify.com> * status Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * update interface Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * credential handler Signed-off-by: runzexia <runzexia@yunify.com> * update devopsoperator func Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * get build sonar Signed-off-by: runzexia <runzexia@yunify.com> * sonar handler * mv code to cilent Signed-off-by: runzexia <runzexia@yunify.com> * update Signed-off-by: runzexia <runzexia@yunify.com> * project member handler Signed-off-by: runzexia <runzexia@yunify.com> * update pipeline operator interface Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add tenant devops handler Signed-off-by: runzexia <runzexia@yunify.com> * update merge Signed-off-by: runzexia <runzexia@yunify.com> * clean Signed-off-by: runzexia <runzexia@yunify.com> * fmt Signed-off-by: runzexia <runzexia@yunify.com> * update ListPipelineRuns Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * complate pipelineOperator interface Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * update HttpParameters Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add pipeline steps interface Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * update pipeline GetNodesDetail Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add s2i api Signed-off-by: runzexia <runzexia@yunify.com> * add branch pipeline interface and update handler Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add scan branch interface and update handler Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add common interface and update handler Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add SCM interface and update handler Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add handler Signed-off-by: runzexia <runzexia@yunify.com> * add fake s3 Signed-off-by: runzexia <runzexia@yunify.com> * add webhook&check interface and update handler Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * clean Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * clean Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * format Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add some func Signed-off-by: runzexia <runzexia@yunify.com> * clean code Signed-off-by: runzexia <runzexia@yunify.com> * implement interface Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * fix interface GetBranchArtifacts Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add s2ibinary upload test Signed-off-by: runzexia <runzexia@yunify.com> * tenant devops Signed-off-by: runzexia <runzexia@yunify.com> * update tenant Signed-off-by: runzexia <runzexia@yunify.com> * fake Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add some unit test Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add devops tenant handler Signed-off-by: runzexia <runzexia@yunify.com> * status Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * status Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * status Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * update fake test Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * update unit test and fake data Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * update Co-authored-by: Xiaoyang Zhu <sunzhu@yunify.com>
115 lines
3.1 KiB
Go
115 lines
3.1 KiB
Go
package devops
|
|
|
|
import (
|
|
"code.cloudfoundry.org/bytefmt"
|
|
"fmt"
|
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/watch"
|
|
clientgotesting "k8s.io/client-go/testing"
|
|
"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
|
"kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
|
|
ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
|
|
fakeS3 "kubesphere.io/kubesphere/pkg/simple/client/s3/fake"
|
|
"kubesphere.io/kubesphere/pkg/utils/hashutil"
|
|
"mime/multipart"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
fileaContents = "This is a test file."
|
|
fileaKey = "binary"
|
|
fileaName = "filea.txt"
|
|
boundary = `MyBoundary`
|
|
ns = "testns"
|
|
s2ibname = "test"
|
|
)
|
|
|
|
const message = `
|
|
--MyBoundary
|
|
Content-Disposition: form-data; name="binary"; filename="filea.txt"
|
|
Content-Type: text/plain
|
|
|
|
` + fileaContents + `
|
|
--MyBoundary--
|
|
`
|
|
|
|
func TestS2iBinaryUploader(t *testing.T) {
|
|
s2ib := s2ibinary(ns, s2ibname)
|
|
fakeKubeClient := fake.NewSimpleClientset(s2ib)
|
|
fakeWatch := watch.NewFake()
|
|
fakeKubeClient.AddWatchReactor("*", clientgotesting.DefaultWatchReactor(fakeWatch, nil))
|
|
informerFactory := ksinformers.NewSharedInformerFactory(fakeKubeClient, 0)
|
|
stopCh := make(chan struct{})
|
|
s2iInformer := informerFactory.Devops().V1alpha1().S2iBinaries()
|
|
err := s2iInformer.Informer().GetIndexer().Add(s2ib)
|
|
defer close(stopCh)
|
|
informerFactory.Start(stopCh)
|
|
informerFactory.WaitForCacheSync(stopCh)
|
|
|
|
s3 := fakeS3.NewFakeS3()
|
|
uploader := NewS2iBinaryUploader(fakeKubeClient, informerFactory, s3)
|
|
header := prepareFileHeader()
|
|
file, err := header.Open()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
md5, err := hashutil.GetMD5(file)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
wantSpec := v1alpha1.S2iBinarySpec{
|
|
FileName: fileaName,
|
|
MD5: md5,
|
|
Size: bytefmt.ByteSize(uint64(header.Size)),
|
|
}
|
|
|
|
binary, err := uploader.UploadS2iBinary(ns, s2ibname, md5, header)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
wantSpec.UploadTimeStamp = binary.Spec.UploadTimeStamp
|
|
wantSpec.DownloadURL = binary.Spec.DownloadURL
|
|
if !reflect.DeepEqual(binary.Spec, wantSpec) {
|
|
t.Fatalf("s2ibinary spec is not same with expected, get: %+v, expected: %+v", binary, wantSpec)
|
|
}
|
|
|
|
_, ok := s3.Storage[fmt.Sprintf("%s-%s", ns, s2ibname)]
|
|
if !ok {
|
|
t.Fatalf("should get file in s3")
|
|
}
|
|
|
|
time.Sleep(3 * time.Second)
|
|
url, err := uploader.DownloadS2iBinary(ns, s2ibname, fileaName)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if url != fmt.Sprintf("http://%s-%s/%s", ns, s2ibname, fileaName) {
|
|
t.Fatalf("download url is not equal with expected, get: %+v, expected: %+v", url, fmt.Sprintf("http://%s-%s/%s", ns, s2ibname, fileaName))
|
|
}
|
|
}
|
|
|
|
func prepareFileHeader() *multipart.FileHeader {
|
|
reader := strings.NewReader(message)
|
|
multipartReader := multipart.NewReader(reader, boundary)
|
|
form, err := multipartReader.ReadForm(25)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return form.File["binary"][0]
|
|
}
|
|
|
|
func s2ibinary(namespace, name string) *v1alpha1.S2iBinary {
|
|
return &v1alpha1.S2iBinary{
|
|
ObjectMeta: v1.ObjectMeta{
|
|
Name: name,
|
|
Namespace: namespace,
|
|
},
|
|
Spec: v1alpha1.S2iBinarySpec{},
|
|
Status: v1alpha1.S2iBinaryStatus{},
|
|
}
|
|
}
|