Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure Kubernetes version is always parsed as string #9185

Merged
merged 1 commit into from
Jan 20, 2025
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
15 changes: 14 additions & 1 deletion pkg/api/v1alpha1/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,9 @@ type kindObject struct {
// ParseClusterConfigFromContent unmarshalls an API object implementing the KindAccessor interface
// from a multiobject yaml content. It doesn't set defaults nor validates the object.
func ParseClusterConfigFromContent(content []byte, clusterConfig KindAccessor) error {
r := yamlutil.NewYAMLReader(bufio.NewReader(bytes.NewReader(content)))
normalizedConfig := NormalizeKubernetesVersion(string(content))

r := yamlutil.NewYAMLReader(bufio.NewReader(bytes.NewReader([]byte(normalizedConfig))))
for {
d, err := r.Read()
if err == io.EOF {
Expand Down Expand Up @@ -410,6 +412,17 @@ func ValidateClusterNameLength(clusterName string) error {
return nil
}

// NormalizeKubernetesVersion searches the YAML content for the specific string
// `kubernetesVersion: <>` and adds double quotes around the version so that it
// is always interpreted as a string instead of a float64 value.
// Ref: https://github.com/aws/eks-anywhere/issues/9184
func NormalizeKubernetesVersion(yamlContent string) string {
kubernetesVersionRegex := `(?m)(.*kubernetesVersion:\s*)['"]?(1\.[0-9]{2,})['"]?(.*)$`
quotedKubernetesVersionReplacement := `${1}"${2}"${3}`
compiledKubernetesVersionRegex := regexp.MustCompile(kubernetesVersionRegex)
return compiledKubernetesVersionRegex.ReplaceAllString(yamlContent, quotedKubernetesVersionReplacement)
}

func validateClusterConfigName(clusterConfig *Cluster) error {
err := ValidateClusterName(clusterConfig.ObjectMeta.Name)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/v1alpha1/testdata/cluster_1_20.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ spec:
machineGroupRef:
name: eksa-unit-test
kind: VSphereMachineConfig
kubernetesVersion: "1.20"
kubernetesVersion: 1.20
workerNodeGroupConfigurations:
- count: 3
machineGroupRef:
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/v1alpha1/testdata/cluster_1_20_cloudstack.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ spec:
datacenterRef:
kind: CloudStackDatacenterConfig
name: eksa-unit-test
kubernetesVersion: "1.20"
kubernetesVersion: 1.20
workerNodeGroupConfigurations:
- count: 3
machineGroupRef:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ spec:
machineGroupRef:
name: eksa-unit-test
kind: VSphereMachineConfig
kubernetesVersion: "1.20"
kubernetesVersion: 1.20
workerNodeGroupConfigurations:
- count: 3
machineGroupRef:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ spec:
machineGroupRef:
name: eksa-unit-test
kind: VSphereMachineConfig
kubernetesVersion: "1.20"
kubernetesVersion: 1.20
workerNodeGroupConfigurations:
- count: 3
machineGroupRef:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ spec:
machineGroupRef:
name: eksa-unit-test
kind: VSphereMachineConfig
kubernetesVersion: "1.20"
kubernetesVersion: 1.20
workerNodeGroupConfigurations:
- count: 3
machineGroupRef:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ spec:
machineGroupRef:
name: eksa-unit-test
kind: VSphereMachineConfig
kubernetesVersion: "1.20"
kubernetesVersion: 1.20
workerNodeGroupConfigurations:
- count: 3
machineGroupRef:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ spec:
machineGroupRef:
name: eksa-unit-test
kind: VSphereMachineConfig
kubernetesVersion: "1.20"
kubernetesVersion: 1.20
workerNodeGroupConfigurations:
- count: 0
machineGroupRef:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ spec:
machineGroupRef:
name: eksa-unit-test
kind: VSphereMachineConfig
kubernetesVersion: "1.20"
kubernetesVersion: 1.20
workerNodeGroupConfigurations:
- count: 3
machineGroupRef:
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/v1alpha1/testdata/incorrect_indentation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ spec:
machineGroupRef:
name: eksa-unit-test
kind: VSphereMachineConfig
kubernetesVersion: "1.20"
kubernetesVersion: 1.20
workerNodeGroupConfigurations:
- count: 3
machineGroupRef:
Expand Down
6 changes: 3 additions & 3 deletions pkg/cluster/config_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,9 @@ func (c *ConfigManager) unmarshal(yamlManifest []byte) (*parsed, error) {
yamlObjs := separatorRegex.Split(string(yamlManifest), -1)

for _, yamlObj := range yamlObjs {
trimmedYamlObj := strings.TrimSuffix(yamlObj, "\n")
normalizedYamlObj := anywherev1.NormalizeKubernetesVersion(strings.TrimSuffix(yamlObj, "\n"))
k := &basicAPIObject{}
err := yaml.Unmarshal([]byte(trimmedYamlObj), k)
err := yaml.Unmarshal([]byte(normalizedYamlObj), k)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -154,7 +154,7 @@ func (c *ConfigManager) unmarshal(yamlManifest []byte) (*parsed, error) {
continue
}

if err := yaml.Unmarshal([]byte(trimmedYamlObj), obj); err != nil {
if err := yaml.Unmarshal([]byte(normalizedYamlObj), obj); err != nil {
return nil, err
}
parsed.objects.add(obj)
Expand Down
2 changes: 1 addition & 1 deletion pkg/cluster/testdata/cluster_1_19.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ spec:
kind: VSphereMachineConfig
name: eksa-unit-test
- name: workers-2
kubernetesVersion: "1.20"
kubernetesVersion: 1.20
count: 1
machineGroupRef:
kind: VSphereMachineConfig
Expand Down
2 changes: 1 addition & 1 deletion pkg/cluster/testdata/cluster_1_20_cloudstack.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ spec:
datacenterRef:
kind: CloudStackDatacenterConfig
name: eksa-unit-test
kubernetesVersion: "1.20"
kubernetesVersion: 1.20
workerNodeGroupConfigurations:
- count: 3
machineGroupRef:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ spec:
datacenterRef:
kind: CloudStackDatacenterConfig
name: eksa-unit-test
kubernetesVersion: "1.20"
kubernetesVersion: 1.20
workerNodeGroupConfigurations:
- count: 3
machineGroupRef:
Expand Down
2 changes: 1 addition & 1 deletion pkg/cluster/testdata/docker_cluster_oidc_awsiam_flux.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ spec:
name: m-docker
workerNodeGroupConfigurations:
- name: workers-1
kubernetesVersion: "1.20"
kubernetesVersion: 1.20
count: 1
identityProviderRefs:
- kind: OIDCConfig
Expand Down
2 changes: 1 addition & 1 deletion pkg/dependencies/testdata/cluster_tinkerbell.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ spec:
datacenterRef:
kind: TinkerbellDatacenterConfig
name: eksa-unit-test
kubernetesVersion: "1.20"
kubernetesVersion: 1.20
managementCluster:
name: eksa-unit-test
workerNodeGroupConfigurations:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ spec:
workerNodeGroupConfigurations:
- count: 3
name: md-0
kubernetesVersion: "1.20"
kubernetesVersion: 1.20
machineGroupRef:
kind: CloudStackMachineConfig
name: test-md-0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ metadata:
name: eksa-unit-test
namespace: default
spec:
kubernetesVersion: "1.20"
kubernetesVersion: 1.20
controlPlaneConfiguration:
name: eksa-unit-test-cp
count: 3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ spec:
name: test
workerNodeGroupConfigurations:
- count: 1
kubernetesVersion: "1.20"
kubernetesVersion: 1.20
name: md-0
machineGroupRef:
name: test-md
Expand Down
23 changes: 0 additions & 23 deletions pkg/utils/yaml/yaml.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package yaml

import (
"bufio"
"bytes"
"fmt"
"io"

apiyaml "k8s.io/apimachinery/pkg/util/yaml"
"sigs.k8s.io/yaml"
)

Expand All @@ -28,23 +25,3 @@ func Serialize[T any](objs ...T) ([][]byte, error) {
}
return r, nil
}

// SplitDocuments function splits content into individual document parts represented as byte slices.
func SplitDocuments(r io.Reader) ([][]byte, error) {
resources := make([][]byte, 0)

yr := apiyaml.NewYAMLReader(bufio.NewReader(r))
for {
d, err := yr.Read()
if err == io.EOF {
break
}
if err != nil {
return nil, err
}

resources = append(resources, d)
}

return resources, nil
}
79 changes: 25 additions & 54 deletions pkg/utils/yaml/yaml_test.go
Original file line number Diff line number Diff line change
@@ -1,99 +1,70 @@
package yaml_test

import (
"bufio"
"errors"
"strings"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

yamlutil "github.com/aws/eks-anywhere/pkg/utils/yaml"
)

func TestSplitDocuments(t *testing.T) {
func TestJoin(t *testing.T) {
tests := []struct {
name string
input string
expectedDocs [][]byte
expectedErr error
name string
input [][]byte
output []byte
}{
{
name: "Empty input",
input: "",
expectedDocs: [][]byte{},
expectedErr: nil,
name: "Empty input",
input: [][]byte{},
output: []byte{},
},
{
name: "Single document",
input: `apiVersion: v1
input: [][]byte{
[]byte(`apiVersion: v1
kind: Pod
metadata:
name: pod-1
`,
expectedDocs: [][]byte{
[]byte(`apiVersion: v1
`),
},
output: []byte(`apiVersion: v1
kind: Pod
metadata:
name: pod-1
`),
},
expectedErr: nil,
},
{
name: "Multiple documents",
input: `apiVersion: v1
input: [][]byte{
[]byte(`apiVersion: v1
kind: Pod
metadata:
name: pod-1
---
apiVersion: v1
`),
[]byte(`apiVersion: v1
kind: Service
metadata:
name: service-1
`,
expectedDocs: [][]byte{
[]byte(`apiVersion: v1
`),
},
output: []byte(`apiVersion: v1
kind: Pod
metadata:
name: pod-1
`),
[]byte(`apiVersion: v1

---
apiVersion: v1
kind: Service
metadata:
name: service-1
`),
},
expectedErr: nil,
},
{
name: "Error reading input 2",
input: `---\nkey: value\ninvalid_separator\n`,
expectedDocs: nil,
expectedErr: errors.New("invalid Yaml document separator: \\nkey: value\\ninvalid_separator\\n"),
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
r := strings.NewReader(test.input)

docs, err := yamlutil.SplitDocuments(bufio.NewReader(r))
if test.expectedErr != nil {
assert.Equal(t, test.expectedErr.Error(), err.Error())
assert.Equal(t, len(test.expectedDocs), len(docs))
} else {
require.NoError(t, err)
if len(docs) != len(test.expectedDocs) {
t.Errorf("Expected %d documents, but got %d", len(test.expectedDocs), len(docs))
}

for i, doc := range docs {
if string(doc) != string(test.expectedDocs[i]) {
t.Errorf("Document %d mismatch.\nExpected:\n%s\nGot:\n%s", i+1, string(test.expectedDocs[i]), string(doc))
}
}
joinedDoc := yamlutil.Join(test.input)
if string(joinedDoc) != string(test.output) {
t.Errorf("Document mismatch.\nExpected:\n%s\nGot:\n%s", string(test.output), string(joinedDoc))
}
})
}
Expand Down
5 changes: 4 additions & 1 deletion pkg/yamlutil/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
apiyaml "k8s.io/apimachinery/pkg/util/yaml"
"sigs.k8s.io/yaml"

"github.com/aws/eks-anywhere/pkg/api/v1alpha1"
)

type (
Expand Down Expand Up @@ -95,7 +97,8 @@ type Builder interface {
// Parse reads yaml manifest content with the registered mappings and passes
// the result to the Builder for further processing.
func (p *Parser) Parse(yamlManifest []byte, b Builder) error {
return p.Read(bytes.NewReader(yamlManifest), b)
normalizedYamlManifest := v1alpha1.NormalizeKubernetesVersion(string(yamlManifest))
return p.Read(bytes.NewReader([]byte(normalizedYamlManifest)), b)
}

// Read reads yaml manifest content with the registered mappings and passes
Expand Down
2 changes: 2 additions & 0 deletions pkg/yamlutil/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func TestParserParse(t *testing.T) {
apiVersion: v1
data:
Corefile: "d"
kubernetesVersion: 1.30
kind: ConfigMap
metadata:
name: aws-iam-authenticator
Expand Down Expand Up @@ -77,6 +78,7 @@ data:
g.Expect(parser.Parse([]byte(yaml), holder)).To(Succeed())
g.Expect(holder).NotTo(BeNil())
g.Expect(holder.configMap.Data).To(HaveKeyWithValue("Corefile", "d"))
g.Expect(holder.configMap.Data).To(HaveKeyWithValue("kubernetesVersion", "1.30"))
g.Expect(holder.secret.Data["username"]).To(Equal([]byte("admin")))
}

Expand Down
Loading
Loading