Skip to content

Commit b68a6ac

Browse files
authored
Fix and updte webhook proxy (#1333)
1 parent d3dbde7 commit b68a6ac

File tree

8 files changed

+148
-60
lines changed

8 files changed

+148
-60
lines changed

.github/workflows/continuous-integration-workflow.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ jobs:
9090
name: Checkout repository
9191
uses: actions/checkout@v4.2.2
9292
-
93-
name: Setup Go 1.23
93+
name: Setup Go 1.24
9494
uses: actions/setup-go@v5
9595
with:
96-
go-version: 1.23
96+
go-version: 1.24
9797
-
9898
name: Download goimports
9999
run: |
@@ -102,7 +102,7 @@ jobs:
102102
name: Download golangci-lint
103103
run: |
104104
curl -sSfL --output /tmp/golangci-lint.sh https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh
105-
cat /tmp/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.60.1
105+
cat /tmp/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.64.7
106106
-
107107
name: Run linter
108108
working-directory: jenkins/webhook-proxy

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
### Changed
1313
- Updated Aqua CLI ([#1325](https://github.com/opendevstack/ods-core/pull/1325)) & ([#1332](https://github.com/opendevstack/ods-core/pull/1332))
14+
- Fix Jenkins pipeline removal issue and update to golang 1.24 ([#1331](https://github.com/opendevstack/ods-core/issues/1331))
1415

1516
### Fixed
1617

jenkins/ocp-config/deploy/jenkins-webhook-proxy.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ parameters:
2020
required: true
2121
- name: ODS_BITBUCKET_PROJECT
2222
required: true
23+
- name: MAX_DELETION_CHECKS
24+
value: '10'
25+
required: true
2326
- name: WEBHOOK_PROXY_CPU_REQUEST
2427
value: 25m
2528
- name: WEBHOOK_PROXY_CPU_LIMIT
@@ -96,6 +99,10 @@ objects:
9699
value: ${REPO_BASE}
97100
- name: ALLOWED_EXTERNAL_PROJECTS
98101
value: ${ODS_BITBUCKET_PROJECT}
102+
- name: OPENSHIFT_APP_DOMAIN
103+
value: ${OPENSHIFT_APPS_BASEDOMAIN}
104+
- name: MAX_DELETION_CHECKS
105+
value: ${MAX_DELETION_CHECKS}
99106
- name: TRIGGER_SECRET
100107
valueFrom:
101108
secretKeyRef:

jenkins/webhook-proxy/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Build stage
2-
FROM public.ecr.aws/docker/library/golang:1.23-alpine AS builder
2+
FROM public.ecr.aws/docker/library/golang:1.24-alpine AS builder
33

44
RUN apk update && \
55
apk -i upgrade && \

jenkins/webhook-proxy/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fmt:
88

99
lint:
1010
golangci-lint --version
11-
golangci-lint run --go=1.23
11+
golangci-lint run --go=1.24
1212

1313
build: build-linux build-darwin build-windows
1414

jenkins/webhook-proxy/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module github.com/opendevstack/ods-core/jenkins/webhook-proxy
22

3-
go 1.23
3+
go 1.24

jenkins/webhook-proxy/main.go

Lines changed: 112 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ import (
88
"encoding/json"
99
"errors"
1010
"fmt"
11-
"io/ioutil"
11+
"io"
1212
"log"
1313
"math/rand"
1414
"net/http"
1515
"os"
1616
"regexp"
17+
"strconv"
1718
"strings"
1819
"sync"
1920
"text/template"
@@ -36,8 +37,12 @@ const (
3637
acceptedEventsDefault = "repo:refs_changed,pr:declined,pr:merged,pr:deleted"
3738
openShiftAPIHostEnvVar = "OPENSHIFT_API_HOST"
3839
openShiftAPIHostDefault = "openshift.default.svc.cluster.local"
40+
openShiftAppDomainEnvVar = "OPENSHIFT_APP_DOMAIN"
41+
openShiftAppDomainDefault = ".apps.default.ocp.openshift.com"
3942
allowedExternalProjectsEnvVar = "ALLOWED_EXTERNAL_PROJECTS"
4043
allowedExternalProjectsDefault = "opendevstack"
44+
maxDeletionChecksEnvVar = "MAX_DELETION_CHECKS"
45+
maxDeletionChecksDefault = "10"
4146
allowedChangeRefTypesEnvVar = "ALLOWED_CHANGE_REF_TYPES"
4247
allowedChangeRefTypesDefault = "BRANCH"
4348
namespaceSuffix = "-cd"
@@ -77,28 +82,24 @@ type BuildConfigData struct {
7782
// buildConfig represents the relevant fields of an OpenShift BuildConfig, see
7883
// https://docs.openshift.com/container-platform/3.11/rest_api/apis-build.openshift.io/v1.BuildConfig.html#object-schema.
7984
type buildConfig struct {
80-
Metadata struct {
81-
ResourceVersion string `json:"resourceVersion"`
82-
} `json:"metadata"`
83-
Spec struct {
84-
Source struct {
85-
Git struct {
86-
Ref string `json:"ref"`
87-
} `json:"git"`
88-
} `json:"source"`
89-
Strategy struct {
90-
JenkinsPipelineStrategy struct {
91-
JenkinsfilePath string `json:"jenkinsfilePath"`
92-
} `json:"jenkinsPipelineStrategy"`
93-
} `json:"strategy"`
94-
Triggers []struct {
95-
Type string `json:"type"`
96-
// Generic struct {
97-
// Secret string `json:"secret"`
98-
// AllowEnv bool `json:"allowEnv"`
99-
// } `json:"generic"`
100-
} `json:"triggers"`
101-
} `json:"spec"`
85+
Metadata struct {
86+
ResourceVersion string `json:"resourceVersion"`
87+
} `json:"metadata"`
88+
Spec struct {
89+
Source struct {
90+
Git struct {
91+
Ref string `json:"ref"`
92+
} `json:"git"`
93+
} `json:"source"`
94+
Strategy struct {
95+
JenkinsPipelineStrategy struct {
96+
JenkinsfilePath string `json:"jenkinsfilePath"`
97+
} `json:"jenkinsPipelineStrategy"`
98+
} `json:"strategy"`
99+
Triggers []struct {
100+
Type string `json:"type"`
101+
} `json:"triggers"`
102+
} `json:"spec"`
102103
}
103104

104105
// Client makes requests, e.g. to create and delete pipelines, or to forward
@@ -116,6 +117,7 @@ type ocClient struct {
116117
HTTPClient *http.Client
117118
OpenShiftAPIBaseURL string
118119
Token string
120+
OpenShiftAppDomain string
119121
}
120122

121123
// Server represents this service, and is a global.
@@ -129,10 +131,11 @@ type Server struct {
129131
AllowedExternalProjects []string
130132
AllowedChangeRefTypes []string
131133
RepoBase string
134+
MaxDeletionChecks int
132135
}
133136

134137
func init() {
135-
rand.Seed(time.Now().UnixNano())
138+
rand.New(rand.NewSource(time.Now().UnixNano()))
136139
}
137140

138141
func main() {
@@ -193,6 +196,17 @@ func main() {
193196
)
194197
}
195198

199+
openShiftAppDomain := os.Getenv(openShiftAppDomainEnvVar)
200+
if len(openShiftAppDomain) == 0 {
201+
openShiftAppDomain = openShiftAppDomainDefault
202+
log.Println(
203+
"INFO:",
204+
openShiftAppDomainEnvVar,
205+
"not set, using default value:",
206+
openShiftAppDomainDefault,
207+
)
208+
}
209+
196210
var allowedExternalProjects []string
197211
envAllowedExternalProjects := strings.ToLower(os.Getenv(allowedExternalProjectsEnvVar))
198212
if len(envAllowedExternalProjects) == 0 {
@@ -227,7 +241,13 @@ func main() {
227241
}
228242
}
229243

230-
client, err := newClient(openShiftAPIHost, triggerSecret)
244+
maxDeletionChecks := maxDeletionChecksDefault
245+
envMaxDeletionChecks := os.Getenv(maxDeletionChecksEnvVar)
246+
if len(envMaxDeletionChecks) != 0 {
247+
maxDeletionChecks = envMaxDeletionChecks
248+
}
249+
250+
client, err := newClient(openShiftAPIHost, triggerSecret, openShiftAppDomain)
231251
if err != nil {
232252
log.Fatalln(err)
233253
}
@@ -239,6 +259,11 @@ func main() {
239259

240260
project := strings.TrimSuffix(namespace, namespaceSuffix)
241261

262+
maxDeletionChecksInt, err := strconv.Atoi(maxDeletionChecks)
263+
if err != nil {
264+
log.Fatalln("Invalid max deletion checks value:", maxDeletionChecks)
265+
}
266+
242267
server := &Server{
243268
Client: client,
244269
Namespace: namespace,
@@ -249,6 +274,7 @@ func main() {
249274
AllowedExternalProjects: allowedExternalProjects,
250275
AllowedChangeRefTypes: allowedChangeRefTypes,
251276
RepoBase: repoBase,
277+
MaxDeletionChecks: maxDeletionChecksInt,
252278
}
253279

254280
log.Println("Ready to accept requests")
@@ -579,11 +605,28 @@ func (s *Server) HandleRoot() http.HandlerFunc {
579605
)
580606
return
581607
}
582-
err := s.Client.DeletePipeline(event)
583-
if err != nil {
584-
log.Println(requestID, err)
585-
return
608+
for i := 0; i < s.MaxDeletionChecks; i++ {
609+
err := s.Client.DeletePipeline(event)
610+
if err != nil {
611+
log.Println(requestID, err)
612+
return
613+
}
614+
log.Println(requestID, "Pipeline deleted, checking for remaining instances")
615+
time.Sleep(5 * time.Second) // Wait for 5 seconds before checking
616+
exists, _, err := s.Client.GetPipeline(event)
617+
if err != nil {
618+
log.Println(requestID, "Error checking for remaining instances:", err)
619+
return
620+
}
621+
if !exists {
622+
log.Println(requestID, "No remaining instances found")
623+
return
624+
}
625+
if i == s.MaxDeletionChecks - 1 {
626+
log.Println(requestID, "Reached maximum iterations, stopping checks")
627+
}
586628
}
629+
587630
} else {
588631
log.Println(requestID, "Unrecognized event")
589632
}
@@ -636,7 +679,7 @@ func (c *ocClient) Forward(e *Event, triggerSecret string) (int, []byte, error)
636679
}
637680
defer res.Body.Close()
638681

639-
body, err := ioutil.ReadAll(res.Body)
682+
body, err := io.ReadAll(res.Body)
640683
return res.StatusCode, body, err
641684
}
642685

@@ -666,7 +709,7 @@ func (c *ocClient) CreateOrUpdatePipeline(exists bool, tmpl *template.Template,
666709
}
667710
defer res.Body.Close()
668711

669-
body, err := ioutil.ReadAll(res.Body)
712+
body, err := io.ReadAll(res.Body)
670713
if err != nil {
671714
return 500, fmt.Errorf("could not read OpenShift response body: %s", err)
672715
}
@@ -683,6 +726,7 @@ func (c *ocClient) CreateOrUpdatePipeline(exists bool, tmpl *template.Template,
683726
// DeletePipeline removes the pipeline corresponding to the event from
684727
// OpenShift.
685728
func (c *ocClient) DeletePipeline(e *Event) error {
729+
// Delete OpenShift BuildConfig
686730
url := fmt.Sprintf(
687731
"%s/namespaces/%s/buildconfigs/%s?propagationPolicy=Foreground",
688732
c.OpenShiftAPIBaseURL,
@@ -701,13 +745,43 @@ func (c *ocClient) DeletePipeline(e *Event) error {
701745
}
702746
defer res.Body.Close()
703747

704-
body, _ := ioutil.ReadAll(res.Body)
748+
body, _ := io.ReadAll(res.Body)
705749

706750
if res.StatusCode < 200 || res.StatusCode >= 300 {
707751
return errors.New(string(body))
708752
}
709753

710-
log.Println(e.RequestID, "Deleted pipeline", e.Pipeline)
754+
log.Println(e.RequestID, "Deleted Openshift pipeline", e.Pipeline)
755+
756+
// Delete Jenkins pipeline
757+
jenkinsURL := fmt.Sprintf(
758+
"https://jenkins-%s%s/job/%s/job/%s-%s/doDelete",
759+
e.Namespace,
760+
c.OpenShiftAppDomain,
761+
e.Namespace,
762+
e.Namespace,
763+
e.Pipeline,
764+
)
765+
766+
jenkinsReq, _ := http.NewRequest(
767+
"POST",
768+
jenkinsURL,
769+
nil,
770+
)
771+
jenkinsReq.Header.Set("Authorization", "Bearer "+c.Token)
772+
jenkinsRes, err := c.do(jenkinsReq)
773+
if err != nil {
774+
return fmt.Errorf("could not make Jenkins request: %s", err)
775+
}
776+
defer jenkinsRes.Body.Close()
777+
778+
jenkinsBody, _ := io.ReadAll(jenkinsRes.Body)
779+
780+
if jenkinsRes.StatusCode < 200 || jenkinsRes.StatusCode >= 300 {
781+
return errors.New(string(jenkinsBody))
782+
}
783+
784+
log.Println(e.RequestID, "Deleted Jenkins pipeline", e.Pipeline)
711785

712786
return nil
713787
}
@@ -786,7 +860,7 @@ func (c *ocClient) GetPipeline(e *Event) (bool, []byte, error) {
786860
return false, nil, nil
787861
}
788862

789-
body, err := ioutil.ReadAll(res.Body)
863+
body, err := io.ReadAll(res.Body)
790864
if err != nil {
791865
return false, nil, fmt.Errorf("could not read OpenShift response: %s", err)
792866
}
@@ -826,7 +900,7 @@ func (e *Event) String() string {
826900
)
827901
}
828902

829-
func newClient(openShiftAPIHost string, triggerSecret string) (*ocClient, error) {
903+
func newClient(openShiftAPIHost string, triggerSecret string, openShiftAppDomain string) (*ocClient, error) {
830904
token, err := getFileContent(tokenFile)
831905
if err != nil {
832906
return nil, fmt.Errorf("Could not get token: %s", err)
@@ -847,6 +921,7 @@ func newClient(openShiftAPIHost string, triggerSecret string) (*ocClient, error)
847921
HTTPClient: secureClient,
848922
OpenShiftAPIBaseURL: baseURL,
849923
Token: token,
924+
OpenShiftAppDomain: openShiftAppDomain,
850925
}, nil
851926
}
852927

@@ -861,7 +936,7 @@ func getBuildConfig(tmpl *template.Template, data BuildConfigData) (*bytes.Buffe
861936

862937
func getSecureClient() (*http.Client, error) {
863938
// Load CA cert
864-
caCert, err := ioutil.ReadFile(caCert)
939+
caCert, err := os.ReadFile(caCert)
865940
if err != nil {
866941
return nil, err
867942
}
@@ -883,7 +958,7 @@ func getSecureClient() (*http.Client, error) {
883958
}
884959

885960
func getFileContent(filename string) (string, error) {
886-
content, err := ioutil.ReadFile(filename)
961+
content, err := os.ReadFile(filename)
887962
if err != nil {
888963
return "", err
889964
}

0 commit comments

Comments
 (0)