package webhook
import (
"errors"
"io/ioutil"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/openshift/origin/pkg/build/api"
imageapi "github.com/openshift/origin/pkg/image/api"
)
type okImageRepositoryNamespaceGetter struct{}
func (m *okImageRepositoryNamespaceGetter) GetByNamespace(namespace, name string) (*imageapi.ImageRepository, error) {
return &imageapi.ImageRepository{
Status: imageapi.ImageRepositoryStatus{
DockerImageRepository: "repository/image",
},
Tags: map[string]string{
"latest": "latest",
},
}, nil
}
type okBuildConfigGetter struct{}
func (*okBuildConfigGetter) Get(namespace, name string) (*api.BuildConfig, error) {
return &api.BuildConfig{
Parameters: api.BuildParameters{
Strategy: api.BuildStrategy{
Type: "STI",
STIStrategy: &api.STIBuildStrategy{
Image: "repository/builder-image",
},
},
},
Triggers: []api.BuildTriggerPolicy{
{
Type: api.GithubWebHookBuildTriggerType,
GithubWebHook: &api.WebHookTrigger{
Secret: "secret101",
},
},
},
}, nil
}
type okBuildCreator struct{}
func (*okBuildCreator) Create(namespace string, build *api.Build) error {
return nil
}
type errorBuildCreator struct{}
func (*errorBuildCreator) Create(namespace string, build *api.Build) error {
return errors.New("Build error!")
}
type errorBuildConfigGetter struct{}
func (*errorBuildConfigGetter) Get(namespace, name string) (*api.BuildConfig, error) {
return &api.BuildConfig{}, errors.New("BuildConfig error!")
}
type pathPlugin struct {
Path string
}
func (p *pathPlugin) Extract(buildCfg *api.BuildConfig, secret, path string, req *http.Request) (*api.SourceRevision, bool, error) {
p.Path = path
return nil, true, nil
}
type errPlugin struct{}
func (*errPlugin) Extract(buildCfg *api.BuildConfig, secret, path string, req *http.Request) (*api.SourceRevision, bool, error) {
return nil, true, errors.New("Plugin error!")
}
func TestParseUrlError(t *testing.T) {
server := httptest.NewServer(NewController(&okBuildConfigGetter{}, &okBuildCreator{}, &okImageRepositoryNamespaceGetter{}, nil))
defer server.Close()
resp, err := http.Post(server.URL, "application/json", nil)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
body, _ := ioutil.ReadAll(resp.Body)
if resp.StatusCode != http.StatusNotFound {
t.Errorf("Wrong response code, expecting 404, got %s: %s!", resp.Status,
string(body))
}
}
func TestParseUrlOK(t *testing.T) {
server := httptest.NewServer(NewController(&okBuildConfigGetter{}, &okBuildCreator{}, &okImageRepositoryNamespaceGetter{}, map[string]Plugin{
"pathplugin": &pathPlugin{},
}))
defer server.Close()
resp, err := http.Post(server.URL+"/build100/secret101/pathplugin",
"application/json", nil)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
body, _ := ioutil.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK {
t.Errorf("Wrong response code, expecting 200, got %s: %s!", resp.Status,
string(body))
}
}
func TestParseUrlLong(t *testing.T) {
plugin := &pathPlugin{}
server := httptest.NewServer(NewController(&okBuildConfigGetter{}, &okBuildCreator{}, &okImageRepositoryNamespaceGetter{}, map[string]Plugin{
"pathplugin": plugin,
}))
defer server.Close()
resp, err := http.Post(server.URL+"/build100/secret101/pathplugin/some/more/args",
"application/json", nil)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
body, _ := ioutil.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK {
t.Errorf("Wrong response code, expecting 200, got %s: %s!", resp.Status,
string(body))
}
if plugin.Path != "some/more/args" {
t.Errorf("Expected some/more/args got %s!", plugin.Path)
}
}
func TestInvokeWebhookErrorSecret(t *testing.T) {
server := httptest.NewServer(NewController(&okBuildConfigGetter{}, &okBuildCreator{}, &okImageRepositoryNamespaceGetter{}, nil))
defer server.Close()
resp, err := http.Post(server.URL+"/build100/wrongsecret/somePlugin",
"application/json", nil)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
body, _ := ioutil.ReadAll(resp.Body)
if resp.StatusCode != http.StatusBadRequest && len(body) == 0 {
t.Errorf("Wrong response code, expecting 400, got %s: %s!", resp.Status,
string(body))
}
}
func TestInvokeWebhookMissingPlugin(t *testing.T) {
server := httptest.NewServer(NewController(&okBuildConfigGetter{}, &okBuildCreator{}, &okImageRepositoryNamespaceGetter{}, nil))
defer server.Close()
resp, err := http.Post(server.URL+"/build100/secret101/missingplugin",
"application/json", nil)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
body, _ := ioutil.ReadAll(resp.Body)
if resp.StatusCode != http.StatusNotFound &&
!strings.Contains(string(body), "Plugin missingplugin not found") {
t.Errorf("Wrong response code, expecting 400, got %s: %s!", resp.Status,
string(body))
}
}
func TestInvokeWebhookErrorBuildConfig(t *testing.T) {
server := httptest.NewServer(NewController(&okBuildConfigGetter{}, &errorBuildCreator{}, &okImageRepositoryNamespaceGetter{}, map[string]Plugin{
"okPlugin": &pathPlugin{},
}))
defer server.Close()
resp, err := http.Post(server.URL+"/build100/secret101/okPlugin",
"application/json", nil)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
body, _ := ioutil.ReadAll(resp.Body)
if resp.StatusCode != http.StatusBadRequest &&
!strings.Contains(string(body), "Build error!") {
t.Errorf("Wrong response code, expecting 400, got %s: %s!", resp.Status,
string(body))
}
}
func TestInvokeWebhookErrorGetConfig(t *testing.T) {
server := httptest.NewServer(NewController(&errorBuildConfigGetter{}, &okBuildCreator{}, &okImageRepositoryNamespaceGetter{}, nil))
defer server.Close()
resp, err := http.Post(server.URL+"/build100/secret101/errPlugin",
"application/json", nil)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
body, _ := ioutil.ReadAll(resp.Body)
if resp.StatusCode != http.StatusBadRequest &&
!strings.Contains(string(body), "BuildConfig error!") {
t.Errorf("Wrong response code, expecting 400, got %s: %s!", resp.Status,
string(body))
}
}
func TestInvokeWebhookErrorCreateBuild(t *testing.T) {
server := httptest.NewServer(NewController(&okBuildConfigGetter{}, &okBuildCreator{}, &okImageRepositoryNamespaceGetter{}, map[string]Plugin{
"errPlugin": &errPlugin{},
}))
defer server.Close()
resp, err := http.Post(server.URL+"/build100/secret101/errPlugin",
"application/json", nil)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
body, _ := ioutil.ReadAll(resp.Body)
if resp.StatusCode != http.StatusBadRequest &&
!strings.Contains(string(body), "Plugin error!") {
t.Errorf("Wrong response code, expecting 400, got %s: %s!", resp.Status,
string(body))
}
}
type mockOkBuildCreator struct {
testBuildInterface
}
type testBuildInterface struct {
CreateFunc func(namespace string, build *api.Build) error
}
func (i *testBuildInterface) Create(namespace string, build *api.Build) error {
return i.CreateFunc(namespace, build)
}
type mockOkBuildConfigGetter struct {
testBuildConfigInterface
}
type testBuildConfigInterface struct {
GetBuildConfigFunc func(namespace, name string) (*api.BuildConfig, error)
}
func (i *testBuildConfigInterface) Get(namespace, name string) (*api.BuildConfig, error) {
return i.GetBuildConfigFunc(namespace, name)
}
func TestInvokeWebhookOk(t *testing.T) {
var buildRequest *api.Build
buildConfig := &api.BuildConfig{
Parameters: api.BuildParameters{
Strategy: api.BuildStrategy{
Type: "STI",
STIStrategy: &api.STIBuildStrategy{
Image: "repository/builder-image",
},
},
},
}
server := httptest.NewServer(NewController(
&mockOkBuildConfigGetter{
testBuildConfigInterface: testBuildConfigInterface{
GetBuildConfigFunc: func(namespace, name string) (*api.BuildConfig, error) {
buildConfig.Name = name
return buildConfig, nil
},
},
},
&mockOkBuildCreator{
testBuildInterface: testBuildInterface{
CreateFunc: func(namespace string, build *api.Build) error {
buildRequest = build
return nil
},
},
},
&okImageRepositoryNamespaceGetter{},
map[string]Plugin{
"okPlugin": &pathPlugin{},
}))
defer server.Close()
resp, err := http.Post(server.URL+"/build100/secret101/okPlugin",
"application/json", nil)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
body, _ := ioutil.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK {
t.Errorf("Wrong response code, expecting 200, got %s: %s!", resp.Status,
string(body))
}
if e, a := buildConfig.Name, buildRequest.Labels[api.BuildConfigLabel]; e != a {
t.Fatalf("expected buildconfig names to match '%s', got '%s'", e, a)
}
}