Skip to content

Commit

Permalink
Adding extract pattern validation
Browse files Browse the repository at this point in the history
Signed-off-by: Jonathan Innis <[email protected]>
  • Loading branch information
jonathan-innis committed Feb 9, 2021
1 parent ade6bfc commit eb7102e
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 3 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -166,13 +166,13 @@ jobs:
./bin/flux create image repository podinfo \
--image=ghcr.io/stefanprodan/podinfo \
--interval=1m
- name: flux create image policy select-semver
- name: flux create image policy
run: |
./bin/flux create image policy podinfo-semver \
./bin/flux create image policy podinfo \
--image-ref=podinfo \
--interval=1m \
--select-semver=5.0.x
- name: flux create image policy select-alpha
- name: flux create image policy podinfo-select-alpha
run: |
./bin/flux create image policy podinfo-alpha \
--image-ref=podinfo \
Expand Down
104 changes: 104 additions & 0 deletions cmd/flux/create_image_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ package main

import (
"fmt"
"regexp/syntax"
"strings"
"unicode"
"unicode/utf8"

"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -94,6 +98,8 @@ func createImagePolicyRun(cmd *cobra.Command, args []string) error {
}

switch {
case imagePolicyArgs.semver != "" && imagePolicyArgs.alpha != "":
return fmt.Errorf("policy cannot be specified with both --select-semver and --select-alpha")
case imagePolicyArgs.semver != "":
policy.Spec.Policy.SemVer = &imagev1.SemVerPolicy{
Range: imagePolicyArgs.semver,
Expand All @@ -110,11 +116,18 @@ func createImagePolicyRun(cmd *cobra.Command, args []string) error {
}

if imagePolicyArgs.filterRegex != "" {
exp, err := syntax.Parse(imagePolicyArgs.filterRegex, syntax.Perl)
if err != nil {
return fmt.Errorf("--filter-regex is an invalid regex pattern")
}
policy.Spec.FilterTags = &imagev1.TagFilter{
Pattern: imagePolicyArgs.filterRegex,
}

if imagePolicyArgs.filterExtract != "" {
if err := validateExtractStr(imagePolicyArgs.filterExtract, exp.CapNames()); err != nil {
return err
}
policy.Spec.FilterTags.Extract = imagePolicyArgs.filterExtract
}
} else if imagePolicyArgs.filterExtract != "" {
Expand All @@ -134,3 +147,94 @@ func createImagePolicyRun(cmd *cobra.Command, args []string) error {
})
return err
}

// Performs a dry-run of the extract function in Regexp to validate the template
func validateExtractStr(template string, capNames []string) error {
for len(template) > 0 {
i := strings.Index(template, "$")
if i < 0 {
return nil
}
template = template[i:]
if len(template) > 1 && template[1] == '$' {
template = template[2:]
continue
}
name, num, rest, ok := extract(template)
if !ok {
// Malformed extract string, assume user didn't want this
template = template[1:]
return fmt.Errorf("--filter-extract is malformed")
}
template = rest
if num >= 0 {
// we won't worry about numbers as we can't validate these
continue
} else {
found := false
for _, capName := range capNames {
if name == capName {
found = true
}
}
if !found {
return fmt.Errorf("capture group $%s used in --filter-extract not found in --filter-regex", name)
}
}

}
return nil
}

// extract method from the regexp package
// returns the name or number of the value prepended by $
func extract(str string) (name string, num int, rest string, ok bool) {
if len(str) < 2 || str[0] != '$' {
return
}
brace := false
if str[1] == '{' {
brace = true
str = str[2:]
} else {
str = str[1:]
}
i := 0
for i < len(str) {
rune, size := utf8.DecodeRuneInString(str[i:])
if !unicode.IsLetter(rune) && !unicode.IsDigit(rune) && rune != '_' {
break
}
i += size
}
if i == 0 {
// empty name is not okay
return
}
name = str[:i]
if brace {
if i >= len(str) || str[i] != '}' {
// missing closing brace
return
}
i++
}

// Parse number.
num = 0
for i := 0; i < len(name); i++ {
if name[i] < '0' || '9' < name[i] || num >= 1e8 {
num = -1
break
}
num = num*10 + int(name[i]) - '0'
}
// Disallow leading zeros.
if name[0] == '0' && len(name) > 1 {
num = -1
}

rest = str[i:]
ok = true
return
}

0 comments on commit eb7102e

Please sign in to comment.