Skip to content
This repository has been archived by the owner on Jul 4, 2024. It is now read-only.

Commit

Permalink
feat: upgraded score-go to 1.1.0 and supressed double error printing (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
astromechza authored Feb 27, 2024
2 parents d29b2df + 43ac4f6 commit 6f03e1a
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 67 deletions.
2 changes: 1 addition & 1 deletion cmd/score-helm/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
func main() {

if err := command.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
_, _ = fmt.Fprintln(os.Stderr, "Error: "+err.Error())
os.Exit(1)
}
}
6 changes: 4 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
module github.com/score-spec/score-helm

go 1.19
go 1.22

toolchain go1.22.0

require (
github.com/imdario/mergo v0.3.13
github.com/mitchellh/mapstructure v1.5.0
github.com/score-spec/score-go v0.0.0-20230905115428-131acdd2f5cf
github.com/score-spec/score-go v1.1.0
github.com/spf13/cobra v1.6.0
github.com/stretchr/testify v1.8.0
github.com/tidwall/sjson v1.2.5
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4=
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY=
github.com/score-spec/score-go v0.0.0-20230905115428-131acdd2f5cf h1:0Dt+qyYoGTXPPU5Xq/KxLDtQMMA8hX+oJ8EsjFWUajQ=
github.com/score-spec/score-go v0.0.0-20230905115428-131acdd2f5cf/go.mod h1:3l9mvrtYKzxXDQVcYkQBD3ABTPkTzWhUMYNfGlpctoo=
github.com/score-spec/score-go v1.1.0 h1:63WM1u93NtGgMuPtVZ/UBfzg/BpYuY8sBquaL0BkrXU=
github.com/score-spec/score-go v1.1.0/go.mod h1:nt6TOq2Ld9SiH3Fd9NF8tiJ9L7S17OE3FNgCrSet5GQ=
github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI=
github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
Expand Down
6 changes: 4 additions & 2 deletions internal/command/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ package command
import (
"fmt"

"github.com/score-spec/score-helm/internal/version"
"github.com/spf13/cobra"

"github.com/score-spec/score-helm/internal/version"
)

var (
Expand All @@ -21,7 +22,8 @@ var (
Long: `SCORE is a specification for defining environment agnostic configuration for cloud based workloads.
This tool produces a Helm chart from the SCORE specification.
Complete documentation is available at https://score.dev.`,
Version: fmt.Sprintf("%s (build: %s; sha: %s)", version.Version, version.BuildTime, version.GitSHA),
Version: fmt.Sprintf("%s (build: %s; sha: %s)", version.Version, version.BuildTime, version.GitSHA),
SilenceErrors: true,
}
)

Expand Down
17 changes: 16 additions & 1 deletion internal/command/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
loader "github.com/score-spec/score-go/loader"
schema "github.com/score-spec/score-go/schema"
score "github.com/score-spec/score-go/types"

helm "github.com/score-spec/score-helm/internal/helm"
)

Expand Down Expand Up @@ -62,9 +63,14 @@ var runCmd = &cobra.Command{
Use: "run",
Short: "Translate SCORE file into Helm values file",
RunE: run,
// we print errors ourselves at the top level
SilenceErrors: true,
}

func run(cmd *cobra.Command, args []string) error {
// don't print usage if we've parsed the args successfully
cmd.SilenceUsage = true

if !verbose {
log.SetOutput(io.Discard)
}
Expand Down Expand Up @@ -158,6 +164,15 @@ func run(cmd *cobra.Command, args []string) error {
}
}

// Apply upgrades to fix backports or backward incompatible things
if changes, err := schema.ApplyCommonUpgradeTransforms(srcMap); err != nil {
return fmt.Errorf("failed to upgrade spec: %w", err)
} else if len(changes) > 0 {
for _, change := range changes {
log.Printf("Applying upgrade to specification: %s\n", change)
}
}

// Validate SCORE spec
//
if !skipValidation {
Expand All @@ -169,7 +184,7 @@ func run(cmd *cobra.Command, args []string) error {

// Convert SCORE spec
//
var spec score.WorkloadSpec
var spec score.Workload
log.Print("Validating SCORE spec...\n")
if err = mapstructure.Decode(srcMap, &spec); err != nil {
return fmt.Errorf("validating workload spec: %w", err)
Expand Down
74 changes: 50 additions & 24 deletions internal/helm/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,23 @@ import (

// getProbeDetails extracts an httpGet probe details from the source spec.
// Returns nil if the source spec is empty.
func getProbeDetails(probe *score.ContainerProbeSpec) map[string]interface{} {
if probe.HTTPGet.Path == "" {
func getProbeDetails(probe *score.ContainerProbe) map[string]interface{} {
if probe.HttpGet.Path == "" {
return nil
}

var res = map[string]interface{}{
"type": "http",
"path": probe.HTTPGet.Path,
"port": probe.HTTPGet.Port,
"path": probe.HttpGet.Path,
"port": probe.HttpGet.Port,
}

if len(probe.HTTPGet.HTTPHeaders) > 0 {
if len(probe.HttpGet.HttpHeaders) > 0 {
var hdrs = map[string]string{}
for _, hdr := range probe.HTTPGet.HTTPHeaders {
hdrs[hdr.Name] = hdr.Value
for _, hdr := range probe.HttpGet.HttpHeaders {
if hdr.Name != nil && hdr.Value != nil {
hdrs[*hdr.Name] = *hdr.Value
}
}
res["httpHeaders"] = hdrs
}
Expand All @@ -39,7 +41,7 @@ func getProbeDetails(probe *score.ContainerProbeSpec) map[string]interface{} {
}

// ConvertSpec converts SCORE specification into Helm values map.
func ConvertSpec(dest map[string]interface{}, spec *score.WorkloadSpec, values map[string]interface{}) error {
func ConvertSpec(dest map[string]interface{}, spec *score.Workload, values map[string]interface{}) error {
if values == nil {
values = make(map[string]interface{})
}
Expand All @@ -48,18 +50,18 @@ func ConvertSpec(dest map[string]interface{}, spec *score.WorkloadSpec, values m
return fmt.Errorf("preparing context: %w", err)
}

if len(spec.Service.Ports) > 0 {
if spec.Service != nil && len(spec.Service.Ports) > 0 {
var ports = make([]interface{}, 0, len(spec.Service.Ports))
for name, port := range spec.Service.Ports {
var pVals = map[string]interface{}{
"name": name,
"port": port.Port,
}
if port.Protocol != "" {
pVals["protocol"] = port.Protocol
if port.Protocol != nil {
pVals["protocol"] = string(*port.Protocol)
}
if port.TargetPort > 0 {
pVals["targetPort"] = port.TargetPort
if port.TargetPort != nil {
pVals["targetPort"] = *port.TargetPort
}
ports = append(ports, pVals)
}
Expand Down Expand Up @@ -110,32 +112,56 @@ func ConvertSpec(dest map[string]interface{}, spec *score.WorkloadSpec, values m
var source = context.Substitute(vol.Source)
var vVals = map[string]interface{}{
"name": source,
"subPath": vol.Path,
"mountPath": vol.Target,
"readOnly": vol.ReadOnly,
}
if vol.Path != nil {
vVals["subPath"] = *vol.Path
}
if vol.ReadOnly != nil {
vVals["readOnly"] = *vol.ReadOnly
}
volumes = append(volumes, vVals)
}
cVals["volumeMounts"] = volumes
}

if probe := getProbeDetails(&cSpec.LivenessProbe); len(probe) > 0 {
cVals["livenessProbe"] = probe
if cSpec.LivenessProbe != nil {
if probe := getProbeDetails(cSpec.LivenessProbe); len(probe) > 0 {
cVals["livenessProbe"] = probe
}
}
if probe := getProbeDetails(&cSpec.ReadinessProbe); len(probe) > 0 {
cVals["readinessProbe"] = probe
if cSpec.ReadinessProbe != nil {
if probe := getProbeDetails(cSpec.ReadinessProbe); len(probe) > 0 {
cVals["readinessProbe"] = probe
}
}

if len(cSpec.Resources.Requests) > 0 || len(cSpec.Resources.Limits) > 0 {
cVals["resources"] = map[string]interface{}{
"requests": cSpec.Resources.Requests,
"limits": cSpec.Resources.Limits,
if cSpec.Resources != nil {
containerResources := make(map[string]interface{})
if out := getContainerResources(cSpec.Resources.Limits); len(out) > 0 {
containerResources["limits"] = out
}
if out := getContainerResources(cSpec.Resources.Requests); len(out) > 0 {
containerResources["requests"] = out
}
if len(containerResources) > 0 {
cVals["resources"] = containerResources
}
}

containers[name] = cVals
}
dest["containers"] = containers

return nil
}

func getContainerResources(requests *score.ResourcesLimits) map[string]interface{} {
out := make(map[string]interface{})
if requests.Cpu != nil {
out["cpu"] = *requests.Cpu
}
if requests.Memory != nil {
out["memory"] = *requests.Memory
}
return out
}
42 changes: 21 additions & 21 deletions internal/helm/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
func TestScoreConvert(t *testing.T) {
var tests = []struct {
Name string
Spec *score.WorkloadSpec
Spec *score.Workload
Values map[string]interface{}
Expected map[string]interface{}
Error error
Expand All @@ -26,24 +26,24 @@ func TestScoreConvert(t *testing.T) {
//
{
Name: "Should convert SCORE to Helm values",
Spec: &score.WorkloadSpec{
Metadata: score.WorkloadMeta{
Name: "test",
Spec: &score.Workload{
Metadata: score.WorkloadMetadata{
"name": "test",
},
Service: score.ServiceSpec{
Ports: score.ServicePortsSpecs{
"www": score.ServicePortSpec{
Service: &score.WorkloadService{
Ports: score.WorkloadServicePorts{
"www": score.ServicePort{
Port: 80,
TargetPort: 8080,
TargetPort: Ref(8080),
},
"admin": score.ServicePortSpec{
"admin": score.ServicePort{
Port: 8080,
Protocol: "UDP",
Protocol: Ref(score.ServicePortProtocolUDP),
},
},
},
Containers: score.ContainersSpecs{
"backend": score.ContainerSpec{
Containers: score.WorkloadContainers{
"backend": score.Container{
Image: "busybox",
Command: []string{
"/bin/sh",
Expand Down Expand Up @@ -97,30 +97,30 @@ func TestScoreConvert(t *testing.T) {
},
{
Name: "Should convert all resources references",
Spec: &score.WorkloadSpec{
Metadata: score.WorkloadMeta{
Name: "test",
Spec: &score.Workload{
Metadata: score.WorkloadMetadata{
"name": "test",
},
Containers: score.ContainersSpecs{
"backend": score.ContainerSpec{
Containers: score.WorkloadContainers{
"backend": score.Container{
Image: "busybox",
Variables: map[string]string{
"DEBUG": "${resources.env.DEBUG}",
"LOGS_LEVEL": "$${LOGS_LEVEL}",
"DOMAIN_NAME": "${resources.dns.domain_name}",
"CONNECTION_STRING": "postgresql://${resources.app-db.host}:${resources.app-db.port}/${resources.app-db.name}",
},
Volumes: []score.VolumeMountSpec{
Volumes: []score.ContainerVolumesElem{
{
Source: "${resources.data}",
Path: "sub/path",
Path: Ref("sub/path"),
Target: "/mnt/data",
ReadOnly: true,
ReadOnly: Ref(true),
},
},
},
},
Resources: map[string]score.ResourceSpec{
Resources: score.WorkloadResources{
"env": {
Type: "environment",
},
Expand Down
5 changes: 5 additions & 0 deletions internal/helm/ref.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package helm

func Ref[k any](input k) *k {
return &input
}
4 changes: 2 additions & 2 deletions internal/helm/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ var (
// templatesContext ia an utility type that provides a context for '${...}' templates substitution
type templatesContext struct {
meta map[string]interface{}
resources score.ResourcesSpecs
resources score.WorkloadResources
values map[string]interface{}
}

// buildContext initializes a new templatesContext instance
func buildContext(metadata score.WorkloadMeta, resources score.ResourcesSpecs, values map[string]interface{}) (*templatesContext, error) {
func buildContext(metadata score.WorkloadMetadata, resources score.WorkloadResources, values map[string]interface{}) (*templatesContext, error) {
var metadataMap = make(map[string]interface{})
if decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
TagName: "json",
Expand Down
24 changes: 12 additions & 12 deletions internal/helm/templates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ import (
)

func TestMapVar(t *testing.T) {
var meta = score.WorkloadMeta{
Name: "test-name",
var meta = score.WorkloadMetadata{
"name": "test-name",
}

var resources = score.ResourcesSpecs{
"env": score.ResourceSpec{
var resources = score.WorkloadResources{
"env": score.Resource{
Type: "environment",
},
"db": score.ResourceSpec{
"db": score.Resource{
Type: "postgres",
},
"dns": score.ResourceSpec{
"dns": score.Resource{
Type: "dns",
},
}
Expand Down Expand Up @@ -64,18 +64,18 @@ func TestMapVar(t *testing.T) {
}

func TestSubstitute(t *testing.T) {
var meta = score.WorkloadMeta{
Name: "test-name",
var meta = score.WorkloadMetadata{
"name": "test-name",
}

var resources = score.ResourcesSpecs{
"env": score.ResourceSpec{
var resources = score.WorkloadResources{
"env": score.Resource{
Type: "environment",
},
"db": score.ResourceSpec{
"db": score.Resource{
Type: "postgres",
},
"dns": score.ResourceSpec{
"dns": score.Resource{
Type: "dns",
},
}
Expand Down

0 comments on commit 6f03e1a

Please sign in to comment.