forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgeneric.go
130 lines (114 loc) · 4.56 KB
/
generic.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package generic
import (
"encoding/json"
"fmt"
"io/ioutil"
"mime"
"net/http"
"github.com/golang/glog"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/util/yaml"
kapi "k8s.io/kubernetes/pkg/apis/core"
buildapi "github.com/openshift/origin/pkg/build/apis/build"
"github.com/openshift/origin/pkg/build/webhook"
)
// WebHookPlugin used for processing manual(or other) webhook requests.
type WebHookPlugin struct{}
// New returns a generic webhook plugin.
func New() *WebHookPlugin {
return &WebHookPlugin{}
}
// Extract services generic webhooks.
func (p *WebHookPlugin) Extract(buildCfg *buildapi.BuildConfig, trigger *buildapi.WebHookTrigger, req *http.Request) (revision *buildapi.SourceRevision, envvars []kapi.EnvVar, dockerStrategyOptions *buildapi.DockerStrategyOptions, proceed bool, err error) {
glog.V(4).Infof("Verifying build request for BuildConfig %s/%s", buildCfg.Namespace, buildCfg.Name)
if err = verifyRequest(req); err != nil {
return revision, envvars, dockerStrategyOptions, false, err
}
contentType := req.Header.Get("Content-Type")
if len(contentType) != 0 {
contentType, _, err = mime.ParseMediaType(contentType)
if err != nil {
return revision, envvars, dockerStrategyOptions, false, errors.NewBadRequest(fmt.Sprintf("error parsing Content-Type: %s", err))
}
}
if req.Body == nil {
return revision, envvars, dockerStrategyOptions, true, nil
}
if contentType != "application/json" && contentType != "application/yaml" {
warning := webhook.NewWarning("invalid Content-Type on payload, ignoring payload and continuing with build")
return revision, envvars, dockerStrategyOptions, true, warning
}
body, err := ioutil.ReadAll(req.Body)
if err != nil {
return revision, envvars, dockerStrategyOptions, false, errors.NewBadRequest(err.Error())
}
if len(body) == 0 {
return revision, envvars, dockerStrategyOptions, true, nil
}
var data buildapi.GenericWebHookEvent
if contentType == "application/yaml" {
body, err = yaml.ToJSON(body)
if err != nil {
warning := webhook.NewWarning(fmt.Sprintf("error converting payload to json: %v, ignoring payload and continuing with build", err))
return revision, envvars, dockerStrategyOptions, true, warning
}
}
if err = json.Unmarshal(body, &data); err != nil {
warning := webhook.NewWarning(fmt.Sprintf("error unmarshalling payload: %v, ignoring payload and continuing with build", err))
return revision, envvars, dockerStrategyOptions, true, warning
}
if len(data.Env) > 0 && trigger.AllowEnv {
envvars = data.Env
}
if data.DockerStrategyOptions != nil {
dockerStrategyOptions = data.DockerStrategyOptions
}
if buildCfg.Spec.Source.Git == nil {
// everything below here is specific to git-based builds
return revision, envvars, dockerStrategyOptions, true, nil
}
if data.Git == nil {
warning := webhook.NewWarning("no git information found in payload, ignoring and continuing with build")
return revision, envvars, dockerStrategyOptions, true, warning
}
if data.Git.Refs != nil {
for _, ref := range data.Git.Refs {
if webhook.GitRefMatches(ref.Ref, webhook.DefaultConfigRef, &buildCfg.Spec.Source) {
revision = &buildapi.SourceRevision{
Git: &ref.GitSourceRevision,
}
return revision, envvars, dockerStrategyOptions, true, nil
}
}
warning := webhook.NewWarning(fmt.Sprintf("skipping build. None of the supplied refs matched %q", buildCfg.Spec.Source.Git.Ref))
return revision, envvars, dockerStrategyOptions, false, warning
}
if !webhook.GitRefMatches(data.Git.Ref, webhook.DefaultConfigRef, &buildCfg.Spec.Source) {
warning := webhook.NewWarning(fmt.Sprintf("skipping build. Branch reference from %q does not match configuration", data.Git.Ref))
return revision, envvars, dockerStrategyOptions, false, warning
}
revision = &buildapi.SourceRevision{
Git: &data.Git.GitSourceRevision,
}
return revision, envvars, dockerStrategyOptions, true, nil
}
// GetTriggers retrieves the WebHookTriggers for this webhook type (if any)
func (p *WebHookPlugin) GetTriggers(buildConfig *buildapi.BuildConfig) ([]*buildapi.WebHookTrigger, error) {
triggers := buildapi.FindTriggerPolicy(buildapi.GenericWebHookBuildTriggerType, buildConfig)
webhookTriggers := []*buildapi.WebHookTrigger{}
for _, trigger := range triggers {
if trigger.GenericWebHook != nil {
webhookTriggers = append(webhookTriggers, trigger.GenericWebHook)
}
}
if len(webhookTriggers) == 0 {
return nil, webhook.ErrHookNotEnabled
}
return webhookTriggers, nil
}
func verifyRequest(req *http.Request) error {
if req.Method != "POST" {
return webhook.MethodNotSupported
}
return nil
}