From e3a06745418ca3b535fd310c25480750d49e15e2 Mon Sep 17 00:00:00 2001 From: Georgi Sabev Date: Mon, 29 Jan 2024 13:49:54 +0000 Subject: [PATCH] Support manifest services without name Both manifest service formats are now supported: ``` services: - my_service - name: your_service ``` Co-authored-by: Danail Branekov --- api/payloads/manifest.go | 17 +++++++ api/payloads/manifest_test.go | 88 +++++++++++++++++++++++++++-------- 2 files changed, 86 insertions(+), 19 deletions(-) diff --git a/api/payloads/manifest.go b/api/payloads/manifest.go index 1777a7631..aadffc755 100644 --- a/api/payloads/manifest.go +++ b/api/payloads/manifest.go @@ -2,12 +2,14 @@ package payloads import ( "errors" + "fmt" "regexp" "code.cloudfoundry.org/korifi/api/repositories" korifiv1alpha1 "code.cloudfoundry.org/korifi/controllers/api/v1alpha1" "code.cloudfoundry.org/korifi/tools" "github.com/jellydator/validation" + "gopkg.in/yaml.v3" "code.cloudfoundry.org/bytefmt" ) @@ -70,6 +72,21 @@ type ManifestApplicationService struct { BindingName *string `json:"binding_name" yaml:"binding_name"` } +func (s *ManifestApplicationService) UnmarshalYAML(value *yaml.Node) error { + if value.Kind == yaml.ScalarNode && value.Tag == "!!str" { + s.Name = value.Value + return nil + } + + type manifestApplicationService ManifestApplicationService + err := value.Decode((*manifestApplicationService)(s)) + if err != nil { + return fmt.Errorf("invalid service: line %d, column %d: %w", value.Line, value.Column, err) + } + + return nil +} + type ManifestRoute struct { Route *string `json:"route" yaml:"route"` } diff --git a/api/payloads/manifest_test.go b/api/payloads/manifest_test.go index a0f691fb0..963b9e6d1 100644 --- a/api/payloads/manifest_test.go +++ b/api/payloads/manifest_test.go @@ -8,6 +8,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" . "github.com/onsi/gomega/gstruct" + "gopkg.in/yaml.v3" ) var _ = Describe("Manifest payload", func() { @@ -739,33 +740,82 @@ var _ = Describe("Manifest payload", func() { }) }) - Describe("ManifestApplicationServices", func() { - var ( - validateErr error - testManifestServices ManifestApplicationService - ) + Describe("ManifestApplicationService", func() { + Describe("Unmarshall", func() { + var ( + unmarshalErr error + serviceString string + unmarshalledService ManifestApplicationService + ) - BeforeEach(func() { - testManifestServices = ManifestApplicationService{ - Name: "my-service", - } - }) + BeforeEach(func() { + serviceString = "name: my-svc" + unmarshalledService = ManifestApplicationService{} + }) - JustBeforeEach(func() { - validateErr = validator.DecodeAndValidateYAMLPayload(createYAMLRequest(testManifestServices), &ManifestApplicationService{}) - }) + JustBeforeEach(func() { + unmarshalErr = yaml.Unmarshal([]byte(serviceString), &unmarshalledService) + }) - It("validates the struct", func() { - Expect(validateErr).NotTo(HaveOccurred()) + It("succeeds", func() { + Expect(unmarshalErr).NotTo(HaveOccurred()) + Expect(unmarshalledService).To(Equal(ManifestApplicationService{ + Name: "my-svc", + })) + }) + + When("the name tag is missing", func() { + BeforeEach(func() { + serviceString = "my-svc" + }) + + It("succeeds", func() { + Expect(unmarshalErr).NotTo(HaveOccurred()) + Expect(unmarshalledService).To(Equal(ManifestApplicationService{ + Name: "my-svc", + })) + }) + + When("the value is not a string", func() { + BeforeEach(func() { + serviceString = "123" + }) + + It("errors", func() { + Expect(unmarshalErr).To(MatchError(ContainSubstring("invalid service"))) + }) + }) + }) }) - When("name is not specified", func() { + Describe("Validate", func() { + var ( + validateErr error + testManifestServices ManifestApplicationService + ) + BeforeEach(func() { - testManifestServices.Name = "" + testManifestServices = ManifestApplicationService{ + Name: "my-service", + } }) - It("returns a validation error", func() { - expectUnprocessableEntityError(validateErr, "name cannot be blank") + JustBeforeEach(func() { + validateErr = validator.DecodeAndValidateYAMLPayload(createYAMLRequest(testManifestServices), &ManifestApplicationService{}) + }) + + It("validates the struct", func() { + Expect(validateErr).NotTo(HaveOccurred()) + }) + + When("name is not specified", func() { + BeforeEach(func() { + testManifestServices.Name = "" + }) + + It("returns a validation error", func() { + expectUnprocessableEntityError(validateErr, "name cannot be blank") + }) }) }) })