Tech QA Feedback & add support for organization level templates
This commit is contained in:
parent
a7ef135403
commit
88a5a8e796
34 changed files with 407 additions and 3009 deletions
|
@ -87,6 +87,7 @@ tasks:
|
||||||
- cmd: go test -count=1 github.com/drone/drone/store/secret/global
|
- cmd: go test -count=1 github.com/drone/drone/store/secret/global
|
||||||
- cmd: go test -count=1 github.com/drone/drone/store/stage
|
- cmd: go test -count=1 github.com/drone/drone/store/stage
|
||||||
- cmd: go test -count=1 github.com/drone/drone/store/step
|
- cmd: go test -count=1 github.com/drone/drone/store/step
|
||||||
|
- cmd: go test -count=1 github.com/drone/drone/store/template
|
||||||
- cmd: go test -count=1 github.com/drone/drone/store/user
|
- cmd: go test -count=1 github.com/drone/drone/store/user
|
||||||
- cmd: docker kill mysql
|
- cmd: docker kill mysql
|
||||||
|
|
||||||
|
@ -120,6 +121,7 @@ tasks:
|
||||||
- cmd: go test -count=1 github.com/drone/drone/store/secret/global
|
- cmd: go test -count=1 github.com/drone/drone/store/secret/global
|
||||||
- cmd: go test -count=1 github.com/drone/drone/store/stage
|
- cmd: go test -count=1 github.com/drone/drone/store/stage
|
||||||
- cmd: go test -count=1 github.com/drone/drone/store/step
|
- cmd: go test -count=1 github.com/drone/drone/store/step
|
||||||
|
- cmd: go test -count=1 github.com/drone/drone/store/template
|
||||||
- cmd: go test -count=1 github.com/drone/drone/store/user
|
- cmd: go test -count=1 github.com/drone/drone/store/user
|
||||||
- cmd: docker kill postgres
|
- cmd: docker kill postgres
|
||||||
silent: true
|
silent: true
|
||||||
|
|
|
@ -34,21 +34,25 @@ type (
|
||||||
Template struct {
|
Template struct {
|
||||||
Id int64 `json:"id,omitempty"`
|
Id int64 `json:"id,omitempty"`
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
Data []byte `json:"data,omitempty"`
|
Namespace string `json:"namespace,omitempty"`
|
||||||
|
Data string `json:"data,omitempty"`
|
||||||
Created int64 `json:"created,omitempty"`
|
Created int64 `json:"created,omitempty"`
|
||||||
Updated int64 `json:"updated,omitempty"`
|
Updated int64 `json:"updated,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TemplateStore manages repository templates.
|
// TemplateStore manages repository templates.
|
||||||
TemplateStore interface {
|
TemplateStore interface {
|
||||||
|
// List returns template list at org level
|
||||||
|
List(ctx context.Context, namespace string) ([]*Template, error)
|
||||||
|
|
||||||
// ListAll returns templates list from the datastore.
|
// ListAll returns templates list from the datastore.
|
||||||
ListAll(ctx context.Context) ([]*Template, error)
|
ListAll(ctx context.Context) ([]*Template, error)
|
||||||
|
|
||||||
// Find returns a template from the datastore.
|
// Find returns a template from the datastore.
|
||||||
Find(ctx context.Context, id int64) (*Template, error)
|
Find(ctx context.Context, id int64) (*Template, error)
|
||||||
|
|
||||||
// FindName returns a template from the datastore by name
|
// FindName returns a template from the data store
|
||||||
FindName(ctx context.Context, name string) (*Template, error)
|
FindName(ctx context.Context, name string, namespace string) (*Template, error)
|
||||||
|
|
||||||
// Create persists a new template to the datastore.
|
// Create persists a new template to the datastore.
|
||||||
Create(ctx context.Context, template *Template) error
|
Create(ctx context.Context, template *Template) error
|
||||||
|
|
|
@ -15,10 +15,11 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/drone/drone/handler/api/template"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/drone/drone/handler/api/template"
|
||||||
|
|
||||||
"github.com/drone/drone/core"
|
"github.com/drone/drone/core"
|
||||||
"github.com/drone/drone/handler/api/acl"
|
"github.com/drone/drone/handler/api/acl"
|
||||||
"github.com/drone/drone/handler/api/auth"
|
"github.com/drone/drone/handler/api/auth"
|
||||||
|
@ -358,12 +359,13 @@ func (s Server) Handler() http.Handler {
|
||||||
})
|
})
|
||||||
|
|
||||||
r.Route("/templates", func(r chi.Router) {
|
r.Route("/templates", func(r chi.Router) {
|
||||||
r.With(acl.CheckMembership(s.Orgs, false)).Get("/", template.HandleList(s.Template))
|
r.With(acl.CheckMembership(s.Orgs, false)).Get("/", template.HandleListAll(s.Template))
|
||||||
r.With(acl.CheckMembership(s.Orgs, true)).Post("/", template.HandleCreate(s.Template))
|
r.With(acl.CheckMembership(s.Orgs, true)).Post("/", template.HandleCreate(s.Template))
|
||||||
r.With(acl.CheckMembership(s.Orgs, false)).Get("/{name}", template.HandleFind(s.Template))
|
r.With(acl.CheckMembership(s.Orgs, false)).Get("/{namespace}", template.HandleList(s.Template))
|
||||||
r.With(acl.CheckMembership(s.Orgs, true)).Put("/{name}", template.HandleUpdate(s.Template))
|
r.With(acl.CheckMembership(s.Orgs, false)).Get("/{namespace}/{name}", template.HandleFind(s.Template))
|
||||||
r.With(acl.CheckMembership(s.Orgs, true)).Patch("/{name}", template.HandleUpdate(s.Template))
|
r.With(acl.CheckMembership(s.Orgs, true)).Put("/{namespace}/{name}", template.HandleUpdate(s.Template))
|
||||||
r.With(acl.CheckMembership(s.Orgs, true)).Delete("/{name}", template.HandleDelete(s.Template))
|
r.With(acl.CheckMembership(s.Orgs, true)).Patch("/{namespace}/{name}", template.HandleUpdate(s.Template))
|
||||||
|
r.With(acl.CheckMembership(s.Orgs, true)).Delete("/{namespace}/{name}", template.HandleDelete(s.Template))
|
||||||
})
|
})
|
||||||
|
|
||||||
r.Route("/system", func(r chi.Router) {
|
r.Route("/system", func(r chi.Router) {
|
||||||
|
|
26
handler/api/template/all.go
Normal file
26
handler/api/template/all.go
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by the Drone Non-Commercial License
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !oss
|
||||||
|
|
||||||
|
package template
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/drone/drone/core"
|
||||||
|
"github.com/drone/drone/handler/api/render"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HandleListAll returns an http.HandlerFunc that writes a json-encoded
|
||||||
|
// list of templates to the response body.
|
||||||
|
func HandleListAll(templateStore core.TemplateStore) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
list, err := templateStore.ListAll(r.Context())
|
||||||
|
if err != nil {
|
||||||
|
render.NotFound(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
render.JSON(w, list, 200)
|
||||||
|
}
|
||||||
|
}
|
82
handler/api/template/all_test.go
Normal file
82
handler/api/template/all_test.go
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by the Drone Non-Commercial License
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !oss
|
||||||
|
|
||||||
|
package template
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/drone/drone/core"
|
||||||
|
"github.com/drone/drone/handler/api/errors"
|
||||||
|
"github.com/drone/drone/mock"
|
||||||
|
"github.com/go-chi/chi"
|
||||||
|
"github.com/golang/mock/gomock"
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
dummyTemplate = &core.Template{
|
||||||
|
Name: "my_template",
|
||||||
|
Data: "my_data",
|
||||||
|
Created: 1,
|
||||||
|
Updated: 2,
|
||||||
|
Namespace: "my_org",
|
||||||
|
}
|
||||||
|
dummyTemplateList = []*core.Template{
|
||||||
|
dummyTemplate,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestHandleAll(t *testing.T) {
|
||||||
|
controller := gomock.NewController(t)
|
||||||
|
defer controller.Finish()
|
||||||
|
|
||||||
|
templates := mock.NewMockTemplateStore(controller)
|
||||||
|
templates.EXPECT().ListAll(gomock.Any()).Return(dummyTemplateList, nil)
|
||||||
|
|
||||||
|
c := new(chi.Context)
|
||||||
|
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
r := httptest.NewRequest("GET", "/", nil)
|
||||||
|
r = r.WithContext(
|
||||||
|
context.WithValue(context.Background(), chi.RouteCtxKey, c),
|
||||||
|
)
|
||||||
|
|
||||||
|
HandleListAll(templates).ServeHTTP(w, r)
|
||||||
|
if got, want := w.Code, http.StatusOK; want != got {
|
||||||
|
t.Errorf("Want response code %d, got %d", want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHandleAll_TemplateListErr(t *testing.T) {
|
||||||
|
controller := gomock.NewController(t)
|
||||||
|
defer controller.Finish()
|
||||||
|
|
||||||
|
templates := mock.NewMockTemplateStore(controller)
|
||||||
|
templates.EXPECT().ListAll(gomock.Any()).Return(nil, errors.ErrNotFound)
|
||||||
|
|
||||||
|
c := new(chi.Context)
|
||||||
|
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
r := httptest.NewRequest("GET", "/", nil)
|
||||||
|
r = r.WithContext(
|
||||||
|
context.WithValue(context.Background(), chi.RouteCtxKey, c),
|
||||||
|
)
|
||||||
|
|
||||||
|
HandleListAll(templates).ServeHTTP(w, r)
|
||||||
|
if got, want := w.Code, http.StatusNotFound; want != got {
|
||||||
|
t.Errorf("Want response code %d, got %d", want, got)
|
||||||
|
}
|
||||||
|
|
||||||
|
got, want := new(errors.Error), errors.ErrNotFound
|
||||||
|
json.NewDecoder(w.Body).Decode(got)
|
||||||
|
if diff := cmp.Diff(got, want); len(diff) != 0 {
|
||||||
|
t.Errorf(diff)
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,7 +15,8 @@ import (
|
||||||
|
|
||||||
type templateInput struct {
|
type templateInput struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Data []byte `json:"data"`
|
Data string `json:"data"`
|
||||||
|
Namespace string `json:"namespace"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleCreate returns an http.HandlerFunc that processes http
|
// HandleCreate returns an http.HandlerFunc that processes http
|
||||||
|
@ -32,6 +33,7 @@ func HandleCreate(templateStore core.TemplateStore) http.HandlerFunc {
|
||||||
t := &core.Template{
|
t := &core.Template{
|
||||||
Name: in.Name,
|
Name: in.Name,
|
||||||
Data: in.Data,
|
Data: in.Data,
|
||||||
|
Namespace: in.Namespace,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = t.Validate()
|
err = t.Validate()
|
||||||
|
|
|
@ -51,7 +51,7 @@ func TestHandleCreate_ValidationErrorName(t *testing.T) {
|
||||||
|
|
||||||
c := new(chi.Context)
|
c := new(chi.Context)
|
||||||
in := new(bytes.Buffer)
|
in := new(bytes.Buffer)
|
||||||
json.NewEncoder(in).Encode(&core.Template{Name: "", Data: []byte("my_data")})
|
json.NewEncoder(in).Encode(&core.Template{Name: "", Data: "my_data"})
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r := httptest.NewRequest("GET", "/", in)
|
r := httptest.NewRequest("GET", "/", in)
|
||||||
|
@ -77,7 +77,7 @@ func TestHandleCreate_ValidationErrorData(t *testing.T) {
|
||||||
|
|
||||||
c := new(chi.Context)
|
c := new(chi.Context)
|
||||||
in := new(bytes.Buffer)
|
in := new(bytes.Buffer)
|
||||||
json.NewEncoder(in).Encode(&core.Template{Name: "my_template", Data: nil})
|
json.NewEncoder(in).Encode(&core.Template{Name: "my_template", Data: ""})
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r := httptest.NewRequest("GET", "/", in)
|
r := httptest.NewRequest("GET", "/", in)
|
||||||
|
|
|
@ -19,8 +19,9 @@ func HandleDelete(template core.TemplateStore) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var (
|
var (
|
||||||
name = chi.URLParam(r, "name")
|
name = chi.URLParam(r, "name")
|
||||||
|
namespace = chi.URLParam(r, "namespace")
|
||||||
)
|
)
|
||||||
s, err := template.FindName(r.Context(), name)
|
s, err := template.FindName(r.Context(), name, namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
render.NotFound(w, err)
|
render.NotFound(w, err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -24,11 +24,12 @@ func TestHandleDelete(t *testing.T) {
|
||||||
defer controller.Finish()
|
defer controller.Finish()
|
||||||
|
|
||||||
template := mock.NewMockTemplateStore(controller)
|
template := mock.NewMockTemplateStore(controller)
|
||||||
template.EXPECT().FindName(gomock.Any(), dummyTemplate.Name).Return(dummyTemplate, nil)
|
template.EXPECT().FindName(gomock.Any(), dummyTemplate.Name, dummyTemplate.Namespace).Return(dummyTemplate, nil)
|
||||||
template.EXPECT().Delete(gomock.Any(), dummyTemplate).Return(nil)
|
template.EXPECT().Delete(gomock.Any(), dummyTemplate).Return(nil)
|
||||||
|
|
||||||
c := new(chi.Context)
|
c := new(chi.Context)
|
||||||
c.URLParams.Add("name", "my_template")
|
c.URLParams.Add("name", "my_template")
|
||||||
|
c.URLParams.Add("namespace", "my_org")
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r := httptest.NewRequest("GET", "/", nil)
|
r := httptest.NewRequest("GET", "/", nil)
|
||||||
|
@ -47,10 +48,11 @@ func TestHandleDelete_TemplateNotFound(t *testing.T) {
|
||||||
defer controller.Finish()
|
defer controller.Finish()
|
||||||
|
|
||||||
template := mock.NewMockTemplateStore(controller)
|
template := mock.NewMockTemplateStore(controller)
|
||||||
template.EXPECT().FindName(gomock.Any(), dummyTemplate.Name).Return(nil, errors.ErrNotFound)
|
template.EXPECT().FindName(gomock.Any(), dummyTemplate.Name, dummyTemplate.Namespace).Return(nil, errors.ErrNotFound)
|
||||||
|
|
||||||
c := new(chi.Context)
|
c := new(chi.Context)
|
||||||
c.URLParams.Add("name", "my_template")
|
c.URLParams.Add("name", "my_template")
|
||||||
|
c.URLParams.Add("namespace", "my_org")
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r := httptest.NewRequest("GET", "/", nil)
|
r := httptest.NewRequest("GET", "/", nil)
|
||||||
|
@ -75,11 +77,12 @@ func TestHandleDelete_DeleteError(t *testing.T) {
|
||||||
defer controller.Finish()
|
defer controller.Finish()
|
||||||
|
|
||||||
template := mock.NewMockTemplateStore(controller)
|
template := mock.NewMockTemplateStore(controller)
|
||||||
template.EXPECT().FindName(gomock.Any(), dummyTemplate.Name).Return(dummyTemplate, nil)
|
template.EXPECT().FindName(gomock.Any(), dummyTemplate.Name, dummyTemplate.Namespace).Return(dummyTemplate, nil)
|
||||||
template.EXPECT().Delete(gomock.Any(), dummyTemplate).Return(errors.ErrNotFound)
|
template.EXPECT().Delete(gomock.Any(), dummyTemplate).Return(errors.ErrNotFound)
|
||||||
|
|
||||||
c := new(chi.Context)
|
c := new(chi.Context)
|
||||||
c.URLParams.Add("name", "my_template")
|
c.URLParams.Add("name", "my_template")
|
||||||
|
c.URLParams.Add("namespace", "my_org")
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r := httptest.NewRequest("GET", "/", nil)
|
r := httptest.NewRequest("GET", "/", nil)
|
||||||
|
|
|
@ -19,8 +19,9 @@ func HandleFind(templateStore core.TemplateStore) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var (
|
var (
|
||||||
name = chi.URLParam(r, "name")
|
name = chi.URLParam(r, "name")
|
||||||
|
namespace = chi.URLParam(r, "namespace")
|
||||||
)
|
)
|
||||||
template, err := templateStore.FindName(r.Context(), name)
|
template, err := templateStore.FindName(r.Context(), name, namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
render.NotFound(w, err)
|
render.NotFound(w, err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -24,10 +24,11 @@ func TestHandleFind(t *testing.T) {
|
||||||
defer controller.Finish()
|
defer controller.Finish()
|
||||||
|
|
||||||
template := mock.NewMockTemplateStore(controller)
|
template := mock.NewMockTemplateStore(controller)
|
||||||
template.EXPECT().FindName(gomock.Any(), dummyTemplate.Name).Return(dummyTemplate, nil)
|
template.EXPECT().FindName(gomock.Any(), dummyTemplate.Name, dummyTemplate.Namespace).Return(dummyTemplate, nil)
|
||||||
|
|
||||||
c := new(chi.Context)
|
c := new(chi.Context)
|
||||||
c.URLParams.Add("name", "my_template")
|
c.URLParams.Add("name", "my_template")
|
||||||
|
c.URLParams.Add("namespace", "my_org")
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r := httptest.NewRequest("GET", "/", nil)
|
r := httptest.NewRequest("GET", "/", nil)
|
||||||
|
@ -46,10 +47,11 @@ func TestHandleFind_TemplateNotFound(t *testing.T) {
|
||||||
defer controller.Finish()
|
defer controller.Finish()
|
||||||
|
|
||||||
template := mock.NewMockTemplateStore(controller)
|
template := mock.NewMockTemplateStore(controller)
|
||||||
template.EXPECT().FindName(gomock.Any(), dummyTemplate.Name).Return(nil, errors.ErrNotFound)
|
template.EXPECT().FindName(gomock.Any(), dummyTemplate.Name, dummyTemplate.Namespace).Return(nil, errors.ErrNotFound)
|
||||||
|
|
||||||
c := new(chi.Context)
|
c := new(chi.Context)
|
||||||
c.URLParams.Add("name", "my_template")
|
c.URLParams.Add("name", "my_template")
|
||||||
|
c.URLParams.Add("namespace", "my_org")
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r := httptest.NewRequest("GET", "/", nil)
|
r := httptest.NewRequest("GET", "/", nil)
|
||||||
|
|
|
@ -9,14 +9,16 @@ package template
|
||||||
import (
|
import (
|
||||||
"github.com/drone/drone/core"
|
"github.com/drone/drone/core"
|
||||||
"github.com/drone/drone/handler/api/render"
|
"github.com/drone/drone/handler/api/render"
|
||||||
|
"github.com/go-chi/chi"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HandleList returns an http.HandlerFunc that writes a json-encoded
|
// HandleList returns an http.HandlerFunc that writes a json-encoded
|
||||||
// list of templates to the response body.
|
// list of templates to the response body by namespace
|
||||||
func HandleList(templateStore core.TemplateStore) http.HandlerFunc {
|
func HandleList(templateStore core.TemplateStore) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
list, err := templateStore.ListAll(r.Context())
|
namespace := chi.URLParam(r, "namespace")
|
||||||
|
list, err := templateStore.List(r.Context(), namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
render.NotFound(w, err)
|
render.NotFound(w, err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
|
package template
|
||||||
|
|
||||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||||
// Use of this source code is governed by the Drone Non-Commercial License
|
// Use of this source code is governed by the Drone Non-Commercial License
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !oss
|
|
||||||
|
|
||||||
package template
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/drone/drone/core"
|
|
||||||
"github.com/drone/drone/handler/api/errors"
|
"github.com/drone/drone/handler/api/errors"
|
||||||
"github.com/drone/drone/mock"
|
"github.com/drone/drone/mock"
|
||||||
"github.com/go-chi/chi"
|
"github.com/go-chi/chi"
|
||||||
|
@ -20,26 +17,15 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
dummyTemplate = &core.Template{
|
|
||||||
Name: "my_template",
|
|
||||||
Data: []byte("my_data"),
|
|
||||||
Created: 1,
|
|
||||||
Updated: 2,
|
|
||||||
}
|
|
||||||
dummyTemplateList = []*core.Template{
|
|
||||||
dummyTemplate,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestHandleList(t *testing.T) {
|
func TestHandleList(t *testing.T) {
|
||||||
controller := gomock.NewController(t)
|
controller := gomock.NewController(t)
|
||||||
defer controller.Finish()
|
defer controller.Finish()
|
||||||
|
|
||||||
templates := mock.NewMockTemplateStore(controller)
|
templates := mock.NewMockTemplateStore(controller)
|
||||||
templates.EXPECT().ListAll(gomock.Any()).Return(dummyTemplateList, nil)
|
templates.EXPECT().List(gomock.Any(), dummyTemplate.Namespace).Return(dummyTemplateList, nil)
|
||||||
|
|
||||||
c := new(chi.Context)
|
c := new(chi.Context)
|
||||||
|
c.URLParams.Add("namespace", "my_org")
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r := httptest.NewRequest("GET", "/", nil)
|
r := httptest.NewRequest("GET", "/", nil)
|
||||||
|
@ -58,9 +44,10 @@ func TestHandleList_TemplateListErr(t *testing.T) {
|
||||||
defer controller.Finish()
|
defer controller.Finish()
|
||||||
|
|
||||||
templates := mock.NewMockTemplateStore(controller)
|
templates := mock.NewMockTemplateStore(controller)
|
||||||
templates.EXPECT().ListAll(gomock.Any()).Return(nil, errors.ErrNotFound)
|
templates.EXPECT().List(gomock.Any(), dummyTemplate.Namespace).Return(nil, errors.ErrNotFound)
|
||||||
|
|
||||||
c := new(chi.Context)
|
c := new(chi.Context)
|
||||||
|
c.URLParams.Add("namespace", "my_org")
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r := httptest.NewRequest("GET", "/", nil)
|
r := httptest.NewRequest("GET", "/", nil)
|
||||||
|
|
|
@ -13,8 +13,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type templateUpdate struct {
|
type templateUpdate struct {
|
||||||
Data *[]byte `json:"data"`
|
Data *string `json:"data"`
|
||||||
Updated *int64 `json:"Updated"`
|
Namespace *string `json:"namespace"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleUpdate returns an http.HandlerFunc that processes http
|
// HandleUpdate returns an http.HandlerFunc that processes http
|
||||||
|
@ -23,6 +23,7 @@ func HandleUpdate(templateStore core.TemplateStore) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var (
|
var (
|
||||||
name = chi.URLParam(r, "name")
|
name = chi.URLParam(r, "name")
|
||||||
|
namespace = chi.URLParam(r, "namespace")
|
||||||
)
|
)
|
||||||
|
|
||||||
in := new(templateUpdate)
|
in := new(templateUpdate)
|
||||||
|
@ -32,7 +33,7 @@ func HandleUpdate(templateStore core.TemplateStore) http.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := templateStore.FindName(r.Context(), name)
|
s, err := templateStore.FindName(r.Context(), name, namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
render.NotFound(w, err)
|
render.NotFound(w, err)
|
||||||
return
|
return
|
||||||
|
@ -41,8 +42,8 @@ func HandleUpdate(templateStore core.TemplateStore) http.HandlerFunc {
|
||||||
if in.Data != nil {
|
if in.Data != nil {
|
||||||
s.Data = *in.Data
|
s.Data = *in.Data
|
||||||
}
|
}
|
||||||
if in.Updated != nil {
|
if in.Namespace != nil {
|
||||||
s.Updated = *in.Updated
|
s.Namespace = *in.Namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.Validate()
|
err = s.Validate()
|
||||||
|
|
|
@ -26,11 +26,12 @@ func TestHandleUpdate(t *testing.T) {
|
||||||
defer controller.Finish()
|
defer controller.Finish()
|
||||||
|
|
||||||
template := mock.NewMockTemplateStore(controller)
|
template := mock.NewMockTemplateStore(controller)
|
||||||
template.EXPECT().FindName(gomock.Any(), dummyTemplate.Name).Return(dummyTemplate, nil)
|
template.EXPECT().FindName(gomock.Any(), dummyTemplate.Name, dummyTemplate.Namespace).Return(dummyTemplate, nil)
|
||||||
template.EXPECT().Update(gomock.Any(), gomock.Any()).Return(nil)
|
template.EXPECT().Update(gomock.Any(), gomock.Any()).Return(nil)
|
||||||
|
|
||||||
c := new(chi.Context)
|
c := new(chi.Context)
|
||||||
c.URLParams.Add("name", "my_template")
|
c.URLParams.Add("name", "my_template")
|
||||||
|
c.URLParams.Add("namespace", "my_org")
|
||||||
|
|
||||||
in := new(bytes.Buffer)
|
in := new(bytes.Buffer)
|
||||||
json.NewEncoder(in).Encode(dummyTemplate)
|
json.NewEncoder(in).Encode(dummyTemplate)
|
||||||
|
@ -52,10 +53,11 @@ func TestHandleUpdate_ValidationErrorData(t *testing.T) {
|
||||||
defer controller.Finish()
|
defer controller.Finish()
|
||||||
|
|
||||||
template := mock.NewMockTemplateStore(controller)
|
template := mock.NewMockTemplateStore(controller)
|
||||||
template.EXPECT().FindName(gomock.Any(), dummyTemplate.Name).Return(&core.Template{Name: "my_template"}, nil)
|
template.EXPECT().FindName(gomock.Any(), dummyTemplate.Name, dummyTemplate.Namespace).Return(&core.Template{Name: "my_template"}, nil)
|
||||||
|
|
||||||
c := new(chi.Context)
|
c := new(chi.Context)
|
||||||
c.URLParams.Add("name", "my_template")
|
c.URLParams.Add("name", "my_template")
|
||||||
|
c.URLParams.Add("namespace", "my_org")
|
||||||
|
|
||||||
in := new(bytes.Buffer)
|
in := new(bytes.Buffer)
|
||||||
json.NewEncoder(in).Encode(&core.Secret{Data: ""})
|
json.NewEncoder(in).Encode(&core.Secret{Data: ""})
|
||||||
|
@ -83,10 +85,11 @@ func TestHandleUpdate_TemplateNotFound(t *testing.T) {
|
||||||
defer controller.Finish()
|
defer controller.Finish()
|
||||||
|
|
||||||
template := mock.NewMockTemplateStore(controller)
|
template := mock.NewMockTemplateStore(controller)
|
||||||
template.EXPECT().FindName(gomock.Any(), dummyTemplate.Name).Return(nil, errors.ErrNotFound)
|
template.EXPECT().FindName(gomock.Any(), dummyTemplate.Name, dummyTemplate.Namespace).Return(nil, errors.ErrNotFound)
|
||||||
|
|
||||||
c := new(chi.Context)
|
c := new(chi.Context)
|
||||||
c.URLParams.Add("name", "my_template")
|
c.URLParams.Add("name", "my_template")
|
||||||
|
c.URLParams.Add("namespace", "my_org")
|
||||||
|
|
||||||
in := new(bytes.Buffer)
|
in := new(bytes.Buffer)
|
||||||
json.NewEncoder(in).Encode(&core.Secret{})
|
json.NewEncoder(in).Encode(&core.Secret{})
|
||||||
|
@ -114,14 +117,15 @@ func TestHandleUpdate_UpdateError(t *testing.T) {
|
||||||
defer controller.Finish()
|
defer controller.Finish()
|
||||||
|
|
||||||
template := mock.NewMockTemplateStore(controller)
|
template := mock.NewMockTemplateStore(controller)
|
||||||
template.EXPECT().FindName(gomock.Any(), dummyTemplate.Name).Return(&core.Template{Name: "my_template"}, nil)
|
template.EXPECT().FindName(gomock.Any(), dummyTemplate.Name, dummyTemplate.Namespace).Return(&core.Template{Name: "my_template"}, nil)
|
||||||
template.EXPECT().Update(gomock.Any(), gomock.Any()).Return(errors.ErrNotFound)
|
template.EXPECT().Update(gomock.Any(), gomock.Any()).Return(errors.ErrNotFound)
|
||||||
|
|
||||||
c := new(chi.Context)
|
c := new(chi.Context)
|
||||||
c.URLParams.Add("name", "my_template")
|
c.URLParams.Add("name", "my_template")
|
||||||
|
c.URLParams.Add("namespace", "my_org")
|
||||||
|
|
||||||
in := new(bytes.Buffer)
|
in := new(bytes.Buffer)
|
||||||
json.NewEncoder(in).Encode(&core.Template{Data: []byte("my_data")})
|
json.NewEncoder(in).Encode(&core.Template{Data: "my_data"})
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r := httptest.NewRequest("GET", "/", in)
|
r := httptest.NewRequest("GET", "/", in)
|
||||||
|
|
2865
mock/mock_gen.go
2865
mock/mock_gen.go
File diff suppressed because it is too large
Load diff
|
@ -17,7 +17,7 @@ package converter
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/drone/drone/core"
|
"github.com/drone/drone/core"
|
||||||
"github.com/drone/drone/plugin/converter/parser"
|
"github.com/drone/drone/plugin/converter/starlark"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ func (p *starlarkPlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*c
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
file, _ := parser.ParseStarlark(req, nil, nil)
|
file, _ := starlark.Parse(req, nil, nil)
|
||||||
return &core.Config{
|
return &core.Config{
|
||||||
Data: *file,
|
Data: *file,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package parser
|
package starlark
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/drone/drone/core"
|
"github.com/drone/drone/core"
|
|
@ -1,4 +1,18 @@
|
||||||
package parser
|
// Copyright 2019 Drone IO, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package starlark
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -38,7 +52,7 @@ var (
|
||||||
ErrCannotLoad = errors.New("starlark: cannot load external scripts")
|
ErrCannotLoad = errors.New("starlark: cannot load external scripts")
|
||||||
)
|
)
|
||||||
|
|
||||||
func ParseStarlark(req *core.ConvertArgs, template *core.Template, templateData map[string]interface{}) (file *string, err error) {
|
func Parse(req *core.ConvertArgs, template *core.Template, templateData map[string]interface{}) (file *string, err error) {
|
||||||
thread := &starlark.Thread{
|
thread := &starlark.Thread{
|
||||||
Name: "drone",
|
Name: "drone",
|
||||||
Load: noLoad,
|
Load: noLoad,
|
||||||
|
@ -49,13 +63,13 @@ func ParseStarlark(req *core.ConvertArgs, template *core.Template, templateData
|
||||||
}).Traceln(msg)
|
}).Traceln(msg)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
var starlarkFile []byte
|
var starlarkFile string
|
||||||
var starlarkFileName string
|
var starlarkFileName string
|
||||||
if template != nil {
|
if template != nil {
|
||||||
starlarkFile = template.Data
|
starlarkFile = template.Data
|
||||||
starlarkFileName = template.Name
|
starlarkFileName = template.Name
|
||||||
} else {
|
} else {
|
||||||
starlarkFile = []byte(req.Config.Data)
|
starlarkFile = req.Config.Data
|
||||||
starlarkFileName = req.Repo.Config
|
starlarkFileName = req.Repo.Config
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,18 @@
|
||||||
package parser
|
// Copyright 2019 Drone IO, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package starlark
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/drone/drone/core"
|
"github.com/drone/drone/core"
|
||||||
|
@ -31,7 +45,7 @@ func TestParseStarlark(t *testing.T) {
|
||||||
}
|
}
|
||||||
template := &core.Template{
|
template := &core.Template{
|
||||||
Name: "my_template.star",
|
Name: "my_template.star",
|
||||||
Data: before,
|
Data: string(before),
|
||||||
}
|
}
|
||||||
|
|
||||||
templateData := map[string]interface{}{
|
templateData := map[string]interface{}{
|
||||||
|
@ -42,7 +56,7 @@ func TestParseStarlark(t *testing.T) {
|
||||||
|
|
||||||
req.Config.Data = string(before)
|
req.Config.Data = string(before)
|
||||||
|
|
||||||
parsedFile, err := ParseStarlark(req, template, templateData)
|
parsedFile, err := Parse(req, template, templateData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
@ -80,7 +94,7 @@ func TestParseStarlarkNotTemplateFile(t *testing.T) {
|
||||||
req.Repo.Config = "plugin.starlark.star"
|
req.Repo.Config = "plugin.starlark.star"
|
||||||
req.Config.Data = string(before)
|
req.Config.Data = string(before)
|
||||||
|
|
||||||
parsedFile, err := ParseStarlark(req, nil, nil)
|
parsedFile, err := Parse(req, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package parser
|
package starlark
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
|
@ -1,15 +1,31 @@
|
||||||
|
// Copyright 2019 Drone IO, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
package converter
|
package converter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/drone/drone/core"
|
"github.com/drone/drone/core"
|
||||||
|
|
||||||
"github.com/drone/drone/plugin/converter/parser"
|
"github.com/drone/drone/plugin/converter/starlark"
|
||||||
|
|
||||||
"gopkg.in/yaml.v2"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -45,7 +61,7 @@ func (p *templatePlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*c
|
||||||
return nil, ErrTemplateSyntaxErrors
|
return nil, ErrTemplateSyntaxErrors
|
||||||
}
|
}
|
||||||
// get template from db
|
// get template from db
|
||||||
template, err := p.templateStore.FindName(ctx, templateArgs.Load)
|
template, err := p.templateStore.FindName(ctx, templateArgs.Load, req.Repo.Namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@ -57,7 +73,7 @@ func (p *templatePlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*c
|
||||||
strings.HasSuffix(templateArgs.Load, ".star") ||
|
strings.HasSuffix(templateArgs.Load, ".star") ||
|
||||||
strings.HasSuffix(templateArgs.Load, ".starlark") {
|
strings.HasSuffix(templateArgs.Load, ".starlark") {
|
||||||
|
|
||||||
file, err := parser.ParseStarlark(req, template, templateArgs.Data)
|
file, err := starlark.Parse(req, template, templateArgs.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,17 @@
|
||||||
|
// Copyright 2019 Drone IO, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
package converter
|
package converter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -9,6 +23,26 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTemplatePluginConvert(t *testing.T) {
|
func TestTemplatePluginConvert(t *testing.T) {
|
||||||
|
templateArgs, err := ioutil.ReadFile("testdata/starlark.template.yml")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req := &core.ConvertArgs{
|
||||||
|
Build: &core.Build{
|
||||||
|
After: "3d21ec53a331a6f037a91c368710b99387d012c1",
|
||||||
|
},
|
||||||
|
Repo: &core.Repository{
|
||||||
|
Slug: "octocat/hello-world",
|
||||||
|
Config: ".drone.yml",
|
||||||
|
Namespace: "octocat",
|
||||||
|
},
|
||||||
|
Config: &core.Config{
|
||||||
|
Data: string(templateArgs),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
beforeInput, err := ioutil.ReadFile("testdata/starlark.input.star")
|
beforeInput, err := ioutil.ReadFile("testdata/starlark.input.star")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -21,37 +55,18 @@ func TestTemplatePluginConvert(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
templateArgs, err := ioutil.ReadFile("testdata/starlark.template.yml")
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
template := &core.Template{
|
template := &core.Template{
|
||||||
Name: "plugin.starlark",
|
Name: "plugin.starlark",
|
||||||
Data: beforeInput,
|
Data: string(beforeInput),
|
||||||
}
|
}
|
||||||
|
|
||||||
controller := gomock.NewController(t)
|
controller := gomock.NewController(t)
|
||||||
defer controller.Finish()
|
defer controller.Finish()
|
||||||
|
|
||||||
templates := mock.NewMockTemplateStore(controller)
|
templates := mock.NewMockTemplateStore(controller)
|
||||||
templates.EXPECT().FindName(gomock.Any(), template.Name).Return(template, nil)
|
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
|
||||||
|
|
||||||
plugin := Template(templates)
|
plugin := Template(templates)
|
||||||
req := &core.ConvertArgs{
|
|
||||||
Build: &core.Build{
|
|
||||||
After: "3d21ec53a331a6f037a91c368710b99387d012c1",
|
|
||||||
},
|
|
||||||
Repo: &core.Repository{
|
|
||||||
Slug: "octocat/hello-world",
|
|
||||||
Config: ".drone.yml",
|
|
||||||
},
|
|
||||||
Config: &core.Config{
|
|
||||||
Data: string(templateArgs),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
config, err := plugin.Convert(noContext, req)
|
config, err := plugin.Convert(noContext, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -121,24 +136,12 @@ func TestTemplatePluginConvertDroneFileTypePipeline(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTemplatePluginConvertTemplateNotFound(t *testing.T) {
|
func TestTemplatePluginConvertTemplateNotFound(t *testing.T) {
|
||||||
controller := gomock.NewController(t)
|
|
||||||
defer controller.Finish()
|
|
||||||
|
|
||||||
template := &core.Template{
|
|
||||||
Name: "plugin.starlark",
|
|
||||||
Data: nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
templates := mock.NewMockTemplateStore(controller)
|
|
||||||
templates.EXPECT().FindName(gomock.Any(), template.Name).Return(nil, nil)
|
|
||||||
|
|
||||||
templateArgs, err := ioutil.ReadFile("testdata/starlark.template.yml")
|
templateArgs, err := ioutil.ReadFile("testdata/starlark.template.yml")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin := Template(templates)
|
|
||||||
req := &core.ConvertArgs{
|
req := &core.ConvertArgs{
|
||||||
Build: &core.Build{
|
Build: &core.Build{
|
||||||
After: "3d21ec53a331a6f037a91c368710b99387d012c1",
|
After: "3d21ec53a331a6f037a91c368710b99387d012c1",
|
||||||
|
@ -146,10 +149,24 @@ func TestTemplatePluginConvertTemplateNotFound(t *testing.T) {
|
||||||
Repo: &core.Repository{
|
Repo: &core.Repository{
|
||||||
Slug: "octocat/hello-world",
|
Slug: "octocat/hello-world",
|
||||||
Config: ".drone.yml",
|
Config: ".drone.yml",
|
||||||
|
Namespace: "octocat",
|
||||||
},
|
},
|
||||||
Config: &core.Config{Data: string(templateArgs)},
|
Config: &core.Config{Data: string(templateArgs)},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
controller := gomock.NewController(t)
|
||||||
|
defer controller.Finish()
|
||||||
|
|
||||||
|
template := &core.Template{
|
||||||
|
Name: "plugin.starlark",
|
||||||
|
Data: "",
|
||||||
|
}
|
||||||
|
|
||||||
|
templates := mock.NewMockTemplateStore(controller)
|
||||||
|
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(nil, nil)
|
||||||
|
|
||||||
|
plugin := Template(templates)
|
||||||
|
|
||||||
config, err := plugin.Convert(noContext, req)
|
config, err := plugin.Convert(noContext, req)
|
||||||
if config != nil {
|
if config != nil {
|
||||||
t.Errorf("template converter: template name given not found")
|
t.Errorf("template converter: template name given not found")
|
||||||
|
|
18
plugin/converter/testdata/input.jsonnet
vendored
Normal file
18
plugin/converter/testdata/input.jsonnet
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
local stepName = std.extVar("input.my_step");
|
||||||
|
local image = std.extVar("input.my_image");
|
||||||
|
local commands = std.extVar("input.my_command");
|
||||||
|
|
||||||
|
{
|
||||||
|
"kind": "pipeline",
|
||||||
|
"type": "docker",
|
||||||
|
"name": "default",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"name": stepName,
|
||||||
|
"image": image,
|
||||||
|
"commands": [
|
||||||
|
commands
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
6
plugin/converter/testdata/jsonnet.template.yml
vendored
Normal file
6
plugin/converter/testdata/jsonnet.template.yml
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
kind: template
|
||||||
|
load: plugin.jsonnet
|
||||||
|
data:
|
||||||
|
stepName: my_step
|
||||||
|
image: my_image
|
||||||
|
commands: my_command
|
|
@ -664,13 +664,14 @@ CREATE INDEX ix_latest_repo ON latest (latest_repo_id);
|
||||||
`
|
`
|
||||||
|
|
||||||
//
|
//
|
||||||
// 015_create_table_template.sql
|
// 015_create_table_templates.sql
|
||||||
//
|
//
|
||||||
|
|
||||||
var createTableTemplate = `
|
var createTableTemplate = `
|
||||||
CREATE TABLE IF NOT EXISTS template (
|
CREATE TABLE IF NOT EXISTS templates (
|
||||||
template_id INTEGER PRIMARY KEY AUTO_INCREMENT
|
template_id INTEGER PRIMARY KEY AUTO_INCREMENT
|
||||||
,template_name VARCHAR(500)
|
,template_name VARCHAR(500)
|
||||||
|
,template_namespace VARCHAR(50)
|
||||||
,template_data BLOB
|
,template_data BLOB
|
||||||
,template_created INTEGER
|
,template_created INTEGER
|
||||||
,template_updated INTEGER
|
,template_updated INTEGER
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
-- name: create-table-template
|
-- name: create-table-template
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS template (
|
CREATE TABLE IF NOT EXISTS templates (
|
||||||
template_id INTEGER PRIMARY KEY AUTO_INCREMENT
|
template_id INTEGER PRIMARY KEY AUTO_INCREMENT
|
||||||
,template_name VARCHAR(500)
|
,template_name VARCHAR(500)
|
||||||
|
,template_namespace VARCHAR(50)
|
||||||
,template_data BLOB
|
,template_data BLOB
|
||||||
,template_created INTEGER
|
,template_created INTEGER
|
||||||
,template_updated INTEGER
|
,template_updated INTEGER
|
|
@ -642,13 +642,14 @@ CREATE INDEX IF NOT EXISTS ix_latest_repo ON latest (latest_repo_id);
|
||||||
`
|
`
|
||||||
|
|
||||||
//
|
//
|
||||||
// 016_create_template_table.sql
|
// 016_create_template_tables.sql
|
||||||
//
|
//
|
||||||
|
|
||||||
var createTableTemplate = `
|
var createTableTemplate = `
|
||||||
CREATE TABLE IF NOT EXISTS template (
|
CREATE TABLE IF NOT EXISTS templates (
|
||||||
template_id SERIAL PRIMARY KEY
|
template_id SERIAL PRIMARY KEY
|
||||||
,template_name TEXT UNIQUE
|
,template_name TEXT UNIQUE
|
||||||
|
,template_namespace VARCHAR(50)
|
||||||
,template_data BYTEA
|
,template_data BYTEA
|
||||||
,template_created INTEGER
|
,template_created INTEGER
|
||||||
,template_updated INTEGER
|
,template_updated INTEGER
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
-- name: create-table-template
|
-- name: create-table-template
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS template (
|
CREATE TABLE IF NOT EXISTS templates (
|
||||||
template_id SERIAL PRIMARY KEY
|
template_id SERIAL PRIMARY KEY
|
||||||
,template_name TEXT UNIQUE
|
,template_name TEXT UNIQUE
|
||||||
|
,template_namespace VARCHAR(50)
|
||||||
,template_data BYTEA
|
,template_data BYTEA
|
||||||
,template_created INTEGER
|
,template_created INTEGER
|
||||||
,template_updated INTEGER
|
,template_updated INTEGER
|
|
@ -644,13 +644,14 @@ CREATE INDEX IF NOT EXISTS ix_latest_repo ON latest (latest_repo_id);
|
||||||
`
|
`
|
||||||
|
|
||||||
//
|
//
|
||||||
// 015_create_template_table.sql
|
// 015_create_template_tables.sql
|
||||||
//
|
//
|
||||||
|
|
||||||
var createTableTemplate = `
|
var createTableTemplate = `
|
||||||
CREATE TABLE IF NOT EXISTS template (
|
CREATE TABLE IF NOT EXISTS templates (
|
||||||
template_id INTEGER PRIMARY KEY AUTOINCREMENT
|
template_id INTEGER PRIMARY KEY AUTOINCREMENT
|
||||||
,template_name TEXT UNIQUE
|
,template_name TEXT UNIQUE
|
||||||
|
,template_namespace TEXT COLLATE NOCASE
|
||||||
,template_data BLOB
|
,template_data BLOB
|
||||||
,template_created INTEGER
|
,template_created INTEGER
|
||||||
,template_updated INTEGER
|
,template_updated INTEGER
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
-- name: create-table-template
|
-- name: create-table-template
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS template (
|
CREATE TABLE IF NOT EXISTS templates (
|
||||||
template_id INTEGER PRIMARY KEY AUTOINCREMENT
|
template_id INTEGER PRIMARY KEY AUTOINCREMENT
|
||||||
,template_name TEXT UNIQUE
|
,template_name TEXT UNIQUE
|
||||||
|
,template_namespace TEXT COLLATE NOCASE
|
||||||
,template_data BLOB
|
,template_data BLOB
|
||||||
,template_created INTEGER
|
,template_created INTEGER
|
||||||
,template_updated INTEGER
|
,template_updated INTEGER
|
|
@ -8,6 +8,7 @@ package template
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
||||||
"github.com/drone/drone/core"
|
"github.com/drone/drone/core"
|
||||||
"github.com/drone/drone/store/shared/db"
|
"github.com/drone/drone/store/shared/db"
|
||||||
)
|
)
|
||||||
|
@ -18,6 +19,7 @@ func toParams(template *core.Template) (map[string]interface{}, error) {
|
||||||
return map[string]interface{}{
|
return map[string]interface{}{
|
||||||
"template_id": template.Id,
|
"template_id": template.Id,
|
||||||
"template_name": template.Name,
|
"template_name": template.Name,
|
||||||
|
"template_namespace": template.Namespace,
|
||||||
"template_data": template.Data,
|
"template_data": template.Data,
|
||||||
"template_created": template.Created,
|
"template_created": template.Created,
|
||||||
"template_updated": template.Updated,
|
"template_updated": template.Updated,
|
||||||
|
@ -30,6 +32,7 @@ func scanRow(scanner db.Scanner, dst *core.Template) error {
|
||||||
err := scanner.Scan(
|
err := scanner.Scan(
|
||||||
&dst.Id,
|
&dst.Id,
|
||||||
&dst.Name,
|
&dst.Name,
|
||||||
|
&dst.Namespace,
|
||||||
&dst.Data,
|
&dst.Data,
|
||||||
&dst.Created,
|
&dst.Created,
|
||||||
&dst.Updated,
|
&dst.Updated,
|
||||||
|
|
|
@ -23,6 +23,24 @@ type templateStore struct {
|
||||||
db *db.DB
|
db *db.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *templateStore) List(ctx context.Context, namespace string) ([]*core.Template, error) {
|
||||||
|
var out []*core.Template
|
||||||
|
err := s.db.View(func(queryer db.Queryer, binder db.Binder) error {
|
||||||
|
params := map[string]interface{}{"template_namespace": namespace}
|
||||||
|
stmt, args, err := binder.BindNamed(queryNamespace, params)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rows, err := queryer.Query(stmt, args...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
out, err = scanRows(rows)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
return out, err
|
||||||
|
}
|
||||||
|
|
||||||
func (s *templateStore) ListAll(ctx context.Context) ([]*core.Template, error) {
|
func (s *templateStore) ListAll(ctx context.Context) ([]*core.Template, error) {
|
||||||
var out []*core.Template
|
var out []*core.Template
|
||||||
err := s.db.View(func(queryer db.Queryer, binder db.Binder) error {
|
err := s.db.View(func(queryer db.Queryer, binder db.Binder) error {
|
||||||
|
@ -58,14 +76,16 @@ func (s *templateStore) Find(ctx context.Context, id int64) (*core.Template, err
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *templateStore) FindName(ctx context.Context, name string) (*core.Template, error) {
|
func (s *templateStore) FindName(ctx context.Context, name string, namespace string) (*core.Template, error) {
|
||||||
out := &core.Template{Name: name}
|
out := &core.Template{Name: name, Namespace: namespace}
|
||||||
err := s.db.View(func(queryer db.Queryer, binder db.Binder) error {
|
err := s.db.View(func(queryer db.Queryer, binder db.Binder) error {
|
||||||
params, err := toParams(out)
|
params, err := toParams(out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
query, args, err := binder.BindNamed(queryName, params)
|
query, args, err := binder.BindNamed(queryName, params)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -146,7 +166,7 @@ func (s *templateStore) Delete(ctx context.Context, template *core.Template) err
|
||||||
}
|
}
|
||||||
|
|
||||||
const queryKey = queryBase + `
|
const queryKey = queryBase + `
|
||||||
FROM template
|
FROM templates
|
||||||
WHERE template_id = :template_id
|
WHERE template_id = :template_id
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
`
|
`
|
||||||
|
@ -155,24 +175,33 @@ const queryBase = `
|
||||||
SELECT
|
SELECT
|
||||||
template_id
|
template_id
|
||||||
,template_name
|
,template_name
|
||||||
|
,template_namespace
|
||||||
,template_data
|
,template_data
|
||||||
,template_created
|
,template_created
|
||||||
,template_updated
|
,template_updated
|
||||||
`
|
`
|
||||||
|
|
||||||
const queryAll = queryBase + `
|
const queryAll = queryBase + `
|
||||||
FROM template
|
FROM templates
|
||||||
|
ORDER BY template_name
|
||||||
|
`
|
||||||
|
|
||||||
|
const queryNamespace = queryBase + `
|
||||||
|
FROM templates
|
||||||
|
WHERE template_namespace = :template_namespace
|
||||||
ORDER BY template_name
|
ORDER BY template_name
|
||||||
`
|
`
|
||||||
|
|
||||||
const stmtInsert = `
|
const stmtInsert = `
|
||||||
INSERT INTO template (
|
INSERT INTO templates (
|
||||||
template_name
|
template_name
|
||||||
|
,template_namespace
|
||||||
,template_data
|
,template_data
|
||||||
,template_created
|
,template_created
|
||||||
,template_updated
|
,template_updated
|
||||||
) VALUES (
|
) VALUES (
|
||||||
:template_name
|
:template_name
|
||||||
|
,:template_namespace
|
||||||
,:template_data
|
,:template_data
|
||||||
,:template_created
|
,:template_created
|
||||||
,:template_updated
|
,:template_updated
|
||||||
|
@ -180,20 +209,22 @@ INSERT INTO template (
|
||||||
`
|
`
|
||||||
|
|
||||||
const stmtUpdate = `
|
const stmtUpdate = `
|
||||||
UPDATE template SET
|
UPDATE templates SET
|
||||||
template_name = :template_name
|
template_name = :template_name
|
||||||
|
,template_namespace = :template_namespace
|
||||||
,template_data = :template_data
|
,template_data = :template_data
|
||||||
,template_updated = :template_updated
|
,template_updated = :template_updated
|
||||||
WHERE template_id = :template_id
|
WHERE template_id = :template_id
|
||||||
`
|
`
|
||||||
|
|
||||||
const stmtDelete = `
|
const stmtDelete = `
|
||||||
DELETE FROM template
|
DELETE FROM templates
|
||||||
WHERE template_id = :template_id
|
WHERE template_id = :template_id
|
||||||
`
|
`
|
||||||
const queryName = queryBase + `
|
const queryName = queryBase + `
|
||||||
FROM template
|
FROM templates
|
||||||
WHERE template_name = :template_name
|
WHERE template_name = :template_name
|
||||||
|
AND template_namespace = :template_namespace
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
package template
|
package template
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"github.com/drone/drone/core"
|
"github.com/drone/drone/core"
|
||||||
|
@ -37,7 +36,8 @@ func testTemplateCreate(store *templateStore) func(t *testing.T) {
|
||||||
item := &core.Template{
|
item := &core.Template{
|
||||||
Id: 1,
|
Id: 1,
|
||||||
Name: "my_template",
|
Name: "my_template",
|
||||||
Data: []byte("some_template_data"),
|
Namespace: "my_org",
|
||||||
|
Data: "some_template_data",
|
||||||
Created: 1,
|
Created: 1,
|
||||||
Updated: 2,
|
Updated: 2,
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,7 @@ func testTemplateCreate(store *templateStore) func(t *testing.T) {
|
||||||
t.Run("Find", testTemplateFind(store, item))
|
t.Run("Find", testTemplateFind(store, item))
|
||||||
t.Run("FindName", testTemplateFindName(store))
|
t.Run("FindName", testTemplateFindName(store))
|
||||||
t.Run("ListAll", testTemplateListAll(store))
|
t.Run("ListAll", testTemplateListAll(store))
|
||||||
|
t.Run("List", testTemplateList(store))
|
||||||
t.Run("Update", testTemplateUpdate(store))
|
t.Run("Update", testTemplateUpdate(store))
|
||||||
t.Run("Delete", testTemplateDelete(store))
|
t.Run("Delete", testTemplateDelete(store))
|
||||||
}
|
}
|
||||||
|
@ -70,7 +71,7 @@ func testTemplateFind(store *templateStore, template *core.Template) func(t *tes
|
||||||
|
|
||||||
func testTemplateFindName(store *templateStore) func(t *testing.T) {
|
func testTemplateFindName(store *templateStore) func(t *testing.T) {
|
||||||
return func(t *testing.T) {
|
return func(t *testing.T) {
|
||||||
item, err := store.FindName(noContext, "my_template")
|
item, err := store.FindName(noContext, "my_template", "my_org")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
} else {
|
} else {
|
||||||
|
@ -84,9 +85,12 @@ func testTemplate(item *core.Template) func(t *testing.T) {
|
||||||
if got, want := item.Name, "my_template"; got != want {
|
if got, want := item.Name, "my_template"; got != want {
|
||||||
t.Errorf("Want template name %q, got %q", want, got)
|
t.Errorf("Want template name %q, got %q", want, got)
|
||||||
}
|
}
|
||||||
if got, want := item.Data, []byte("some_template_data"); bytes.Compare(got, want) != 0 {
|
if got, want := item.Data, "some_template_data"; got != want {
|
||||||
t.Errorf("Want template data %q, got %q", want, got)
|
t.Errorf("Want template data %q, got %q", want, got)
|
||||||
}
|
}
|
||||||
|
if got, want := item.Namespace, "my_org"; got != want {
|
||||||
|
t.Errorf("Want template org %q, got %q", want, got)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,9 +109,24 @@ func testTemplateListAll(store *templateStore) func(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testTemplateList(store *templateStore) func(t *testing.T) {
|
||||||
|
return func(t *testing.T) {
|
||||||
|
list, err := store.List(noContext, "my_org")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got, want := len(list), 1; got != want {
|
||||||
|
t.Errorf("Want count %d, got %d", want, got)
|
||||||
|
} else {
|
||||||
|
t.Run("Fields", testTemplate(list[0]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testTemplateUpdate(store *templateStore) func(t *testing.T) {
|
func testTemplateUpdate(store *templateStore) func(t *testing.T) {
|
||||||
return func(t *testing.T) {
|
return func(t *testing.T) {
|
||||||
before, err := store.FindName(noContext, "my_template")
|
before, err := store.FindName(noContext, "my_template", "my_org")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
@ -130,7 +149,7 @@ func testTemplateUpdate(store *templateStore) func(t *testing.T) {
|
||||||
|
|
||||||
func testTemplateDelete(store *templateStore) func(t *testing.T) {
|
func testTemplateDelete(store *templateStore) func(t *testing.T) {
|
||||||
return func(t *testing.T) {
|
return func(t *testing.T) {
|
||||||
secret, err := store.FindName(noContext, "my_template")
|
secret, err := store.FindName(noContext, "my_template", "my_org")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in a new issue