Skip to content

Commit

Permalink
Fix jobsink name generator + add unit and fuzz tests
Browse files Browse the repository at this point in the history
Signed-off-by: Pierangelo Di Pilato <[email protected]>
  • Loading branch information
pierDipi committed Nov 18, 2024
1 parent c9fc3cf commit f88177f
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 12 deletions.
24 changes: 12 additions & 12 deletions cmd/jobsink/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ package main

import (
"context"
"crypto/md5" //nolint:gosec
"crypto/md5"

Check failure on line 21 in cmd/jobsink/main.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

G501: Blocklisted import crypto/md5: weak cryptographic primitive (gosec)
//nolint:gosec
"crypto/tls"
"encoding/hex"
"fmt"
"log"
"net/http"
Expand Down Expand Up @@ -231,11 +233,11 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}

id := toIdHashLabelValue(event.Source(), event.ID())
logger.Debug("Getting job for event", zap.String("URI", r.RequestURI), zap.String("id", id))
jobName := toJobName(ref.Name, event.Source(), event.ID())
logger.Debug("Getting job for event", zap.String("URI", r.RequestURI), zap.String("jobName", jobName))

jobs, err := h.k8s.BatchV1().Jobs(js.GetNamespace()).List(r.Context(), metav1.ListOptions{
LabelSelector: jobLabelSelector(ref, id),
LabelSelector: jobLabelSelector(ref, jobName),
Limit: 1,
})
if err != nil {
Expand All @@ -256,16 +258,14 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}

jobName := kmeta.ChildName(ref.Name, id)

logger.Debug("Creating job for event", zap.String("URI", r.RequestURI), zap.String("jobName", jobName))

job := js.Spec.Job.DeepCopy()
job.Name = jobName
if job.Labels == nil {
job.Labels = make(map[string]string, 4)
}
job.Labels[sinks.JobSinkIDLabel] = id
job.Labels[sinks.JobSinkIDLabel] = jobName
job.Labels[sinks.JobSinkNameLabel] = ref.Name
job.OwnerReferences = append(job.OwnerReferences, metav1.OwnerReference{
APIVersion: sinksv.SchemeGroupVersion.String(),
Expand Down Expand Up @@ -332,7 +332,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
Name: jobName,
Namespace: ref.Namespace,
Labels: map[string]string{
sinks.JobSinkIDLabel: id,
sinks.JobSinkIDLabel: jobName,
sinks.JobSinkNameLabel: ref.Name,
},
OwnerReferences: []metav1.OwnerReference{
Expand Down Expand Up @@ -396,8 +396,7 @@ func (h *Handler) handleGet(ctx context.Context, w http.ResponseWriter, r *http.
eventSource := parts[6]
eventID := parts[8]

id := toIdHashLabelValue(eventSource, eventID)
jobName := kmeta.ChildName(ref.Name, id)
jobName := toJobName(ref.Name, eventSource, eventID)

job, err := h.k8s.BatchV1().Jobs(ref.Namespace).Get(r.Context(), jobName, metav1.GetOptions{})
if err != nil {
Expand Down Expand Up @@ -450,6 +449,7 @@ func jobLabelSelector(ref types.NamespacedName, id string) string {
return fmt.Sprintf("%s=%s,%s=%s", sinks.JobSinkIDLabel, id, sinks.JobSinkNameLabel, ref.Name)
}

func toIdHashLabelValue(source, id string) string {
return utils.ToDNS1123Subdomain(fmt.Sprintf("%s", md5.Sum([]byte(fmt.Sprintf("%s-%s", source, id))))) //nolint:gosec
func toJobName(js string, source, id string) string {
h := md5.Sum([]byte(source+id))

Check failure on line 453 in cmd/jobsink/main.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

G401: Use of weak cryptographic primitive (gosec)
return kmeta.ChildName(js, "-" + utils.ToDNS1123Subdomain(hex.EncodeToString(h[:])))
}
90 changes: 90 additions & 0 deletions cmd/jobsink/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package main

Check failure on line 1 in cmd/jobsink/main_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Boilerplate Check (go)

[Go headers] reported by reviewdog 🐶 missing boilerplate: Raw Output: cmd/jobsink/main_test.go:1: missing boilerplate: /* Copyright 2024 The Knative Authors 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. */

Check failure on line 1 in cmd/jobsink/main_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

Please run goimports. diff --git a/cmd/jobsink/main_test.go b/cmd/jobsink/main_test.go index 0862d40..0bf31b5 100644 --- a/cmd/jobsink/main_test.go +++ b/cmd/jobsink/main_test.go @@ -29,7 +29,7 @@ func TestToJobName(t *testing.T) { } for _, tc := range testcases { - t.Run(tc.JobSinkName + "_" + tc.Source + "_" + tc.Id, func(t *testing.T) { + t.Run(tc.JobSinkName+"_"+tc.Source+"_"+tc.Id, func(t *testing.T) { if errs := validation.NameIsDNS1035Label(tc.JobSinkName, false); len(errs) != 0 { t.Errorf("Invalid JobSinkName: %v", errs) }

import (
"testing"

"k8s.io/apimachinery/pkg/api/validation"

"knative.dev/eventing/pkg/utils"
)

type testCase struct {
JobSinkName string
Source string
Id string
}

func TestToJobName(t *testing.T) {
testcases := []testCase{
{
JobSinkName: "job-sink-success",
Source: "mysource3/myservice",
Id: "2234-5678",
},
{
JobSinkName: "a",
Source: "0",
Id: "0",
},
}

for _, tc := range testcases {
t.Run(tc.JobSinkName + "_" + tc.Source + "_" + tc.Id, func(t *testing.T) {
if errs := validation.NameIsDNS1035Label(tc.JobSinkName, false); len(errs) != 0 {
t.Errorf("Invalid JobSinkName: %v", errs)
}

name := toJobName(tc.JobSinkName, tc.Source, tc.Id)
doubleName := toJobName(tc.JobSinkName, tc.Source, tc.Id)
if name != doubleName {
t.Errorf("Before: %q, after: %q", name, doubleName)
}

if got := utils.ToDNS1123Subdomain(name); got != name {
t.Errorf("ToDNS1123Subdomain(Want) returns a different result, Want: %q, Got: %q", name, got)
}

if errs := validation.NameIsDNS1035Label(name, false); len(errs) != 0 {
t.Errorf("toJobName produced invalid name %q given %q, %q, %q: errors: %#v", name, tc.JobSinkName, tc.Source, tc.Id, errs)
}
})
}
}

func FuzzToJobName(f *testing.F) {
testcases := []testCase{
{
JobSinkName: "job-sink-success",
Source: "mysource3/myservice",
Id: "2234-5678",
},
{
JobSinkName: "a",
Source: "0",
Id: "0",
},
}

for _, tc := range testcases {
f.Add(tc.JobSinkName, tc.Source, tc.Id) // Use f.Add to provide a seed corpus
}
f.Fuzz(func(t *testing.T, js, source, id string) {
if errs := validation.NameIsDNS1035Label(js, false); len(errs) != 0 {
t.Skip("Prerequisite: invalid jobsink name")
}

name := toJobName(js, source, id)
doubleName := toJobName(js, source, id)
if name != doubleName {
t.Errorf("Before: %q, after: %q", name, doubleName)
}

if got := utils.ToDNS1123Subdomain(name); got != name {
t.Errorf("ToDNS1123Subdomain(Want) returns a different result, Want: %q, Got: %q", name, got)
}

if errs := validation.NameIsDNS1035Label(name, false); len(errs) != 0 {
t.Errorf("toJobName produced invalid name %q given %q, %q, %q: errors: %#v", name, js, source, id, errs)
}
})
}

0 comments on commit f88177f

Please sign in to comment.