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

feat: upgraded score-go to 1.1.0 and supressed double error printing #30

Merged
merged 1 commit into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading