Skip to content

Commit

Permalink
Merge pull request #58 from spinkube/allow-sha256
Browse files Browse the repository at this point in the history
fix image reference validation and fetching name from it
  • Loading branch information
rajatjindal authored Mar 8, 2024
2 parents 4fd7a1d + fe9a15b commit 971e7f8
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 19 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ toolchain go1.22.0

require (
github.com/gosuri/uitable v0.0.4
github.com/novln/docker-parser v1.0.0
github.com/pelletier/go-toml/v2 v2.1.1
github.com/spf13/cobra v1.8.0
github.com/spf13/pflag v1.0.5
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/novln/docker-parser v1.0.0 h1:PjEBd9QnKixcWczNGyEdfUrP6GR0YUilAqG7Wksg3uc=
github.com/novln/docker-parser v1.0.0/go.mod h1:oCeM32fsoUwkwByB5wVjsrsVQySzPWkl3JdlTn1txpE=
github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY=
github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw=
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
Expand Down Expand Up @@ -145,6 +147,7 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
Expand Down Expand Up @@ -238,6 +241,7 @@ gopkg.in/evanphx/json-patch.v5 v5.8.1 h1:BVxXj2YS+4i9fttNkVvDKi4Pg1pVMpVE8tdEwaK
gopkg.in/evanphx/json-patch.v5 v5.8.1/go.mod h1:/kvTRh1TVm5wuM6OkHxqXtE/1nUZZpihg29RtuIyfvk=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
Expand Down
10 changes: 5 additions & 5 deletions pkg/cmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"fmt"
"os"
"strings"

"github.com/spf13/cobra"
spinv1alpha1 "github.com/spinkube/spin-operator/api/v1alpha1"
Expand All @@ -23,9 +22,10 @@ var deployCmd = &cobra.Command{
Short: "Deploy application to Kubernetes",
Hidden: isExperimentalFlagNotSet,
RunE: func(cmd *cobra.Command, args []string) error {
reference := strings.Split(artifact, ":")[0]
referenceParts := strings.Split(reference, "/")
name := referenceParts[len(referenceParts)-1]
name, err := getNameFromImageReference(artifact)
if err != nil {
return err
}

spinapp := spinv1alpha1.SpinApp{
ObjectMeta: metav1.ObjectMeta{
Expand All @@ -49,7 +49,7 @@ var deployCmd = &cobra.Command{
return nil
}

err := kubeImpl.ApplySpinApp(context.TODO(), &spinapp)
err = kubeImpl.ApplySpinApp(context.TODO(), &spinapp)
if err != nil {
return err
}
Expand Down
35 changes: 21 additions & 14 deletions pkg/cmd/scaffold.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import (
"fmt"
"log"
"os"
"regexp"
"strings"
"text/template"

dockerparser "github.com/novln/docker-parser"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -229,9 +229,10 @@ func scaffold(opts ScaffoldOptions) ([]byte, error) {
}
}

reference := strings.Split(opts.from, ":")[0]
referenceParts := strings.Split(reference, "/")
name := referenceParts[len(referenceParts)-1]
name, err := getNameFromImageReference(opts.from)
if err != nil {
return nil, err
}

config := appConfig{
Name: name,
Expand Down Expand Up @@ -273,16 +274,22 @@ func scaffold(opts ScaffoldOptions) ([]byte, error) {
}

func validateImageReference(imageRef string) bool {
// This regex is designed to match strings that are valid image references, which include an optional registry (like
// "ghcr.io"), a repository name (like "bacongobbler/hello-rust"), and an optional tag (like "1.0.0").
//
// The regex is quite complex, but in general it's looking for sequences of alphanumeric characters, separated by
// periods, underscores, or hyphens, and optionally followed by a slash and more such sequences. The sequences can
// be repeated any number of times. The final sequence can optionally be followed by a colon and another sequence,
// representing the tag.
pattern := `^([a-zA-Z0-9]+(?:[._-][a-zA-Z0-9]+)*/)*([a-zA-Z0-9]+(?:[._-][a-zA-Z0-9]+)*)?(:[a-zA-Z0-9]+(?:[._-][a-zA-Z0-9]+)*)?$|^([a-zA-Z0-9]+(?:[._-][a-zA-Z0-9]+)*/)*([a-zA-Z0-9]+(?:[._-][a-zA-Z0-9]+)*)?(:[a-zA-Z0-9]+(?:[._-][a-zA-Z0-9]+)*)?/([a-zA-Z0-9]+(?:[._-][a-zA-Z0-9]+)*)?(:[a-zA-Z0-9]+(?:[._-][a-zA-Z0-9]+)*)?$`
regex := regexp.MustCompile(pattern)
return regex.MatchString(imageRef)
_, err := dockerparser.Parse(imageRef)
return err == nil
}

func getNameFromImageReference(imageRef string) (string, error) {
ref, err := dockerparser.Parse(imageRef)
if err != nil {
return "", err
}

if strings.Contains(ref.ShortName(), "/") {
parts := strings.Split(ref.ShortName(), "/")
return parts[len(parts)-1], nil
}

return ref.ShortName(), nil
}

func init() {
Expand Down
43 changes: 43 additions & 0 deletions pkg/cmd/scaffold_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ func TestValidateImageReference_ValidImageReference(t *testing.T) {
"ghcr.io/spinkube/spinkube/runtime-class-manager:v1",
"nginx:latest",
"nginx",
"ttl.sh/hello-spinkube@sha256:cc4b191d11728b4e9e024308f0c03aded893da2002403943adc9deb8c4ca1644",
}

for _, tc := range testCases {
Expand All @@ -90,6 +91,48 @@ func TestValidateImageReference_ValidImageReference(t *testing.T) {
}
}

func TestGetNameFromImageReference(t *testing.T) {
testCases := []struct {
reference string
name string
}{
{
reference: "bacongobbler/hello-rust",
name: "hello-rust",
}, {
reference: "bacongobbler/hello-rust:v1.0.0",
name: "hello-rust",
}, {

reference: "ghcr.io/bacongobbler/hello-rust",
name: "hello-rust",
}, {
reference: "ghcr.io/bacongobbler/hello-rust:v1.0.0",
name: "hello-rust",
}, {
reference: "ghcr.io/spinkube/spinkube/runtime-class-manager:v1",
name: "runtime-class-manager",
}, {
reference: "nginx:latest",
name: "nginx",
}, {
reference: "nginx",
name: "nginx",
}, {
reference: "ttl.sh/hello-spinkube@sha256:cc4b191d11728b4e9e024308f0c03aded893da2002403943adc9deb8c4ca1644",
name: "hello-spinkube",
},
}

for _, tc := range testCases {
t.Run(tc.reference, func(t *testing.T) {
actualName, err := getNameFromImageReference(tc.reference)
require.Nil(t, err)
require.Equal(t, tc.name, actualName, "Expected image name from reference")
})
}
}

func TestFlagValidation(t *testing.T) {
testcases := []struct {
name string
Expand Down

0 comments on commit 971e7f8

Please sign in to comment.