Skip to content

Commit

Permalink
support labels with empty value (#722)
Browse files Browse the repository at this point in the history
* support labels with empty value

* support labels with empty value

* support labels with empty value

* support labels with empty value

* support labels with empty value

* support labels with empty value

* support labels with empty value
  • Loading branch information
I065450 authored Nov 28, 2021
1 parent 7114f8d commit 53c01a9
Show file tree
Hide file tree
Showing 10 changed files with 155 additions and 21 deletions.
29 changes: 18 additions & 11 deletions pkg/query/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,11 @@ func ApplyLabelChangesToLabels(changes types.LabelChanges, labels types.Labels)
case types.AddLabelOperation:
fallthrough
case types.AddLabelValuesOperation:
if len(change.Values) == 0 {
addValue(mergedLabels, change, "", labelsToAdd)
}
for _, value := range change.Values {
found := false
for _, currentValue := range mergedLabels[change.Key] {
if currentValue == value {
found = true
break
}
}
if !found {
labelsToAdd[change.Key] = append(labelsToAdd[change.Key], value)
mergedLabels[change.Key] = append(mergedLabels[change.Key], value)
}
addValue(mergedLabels, change, value, labelsToAdd)
}
case types.RemoveLabelOperation:
fallthrough
Expand All @@ -88,3 +81,17 @@ func ApplyLabelChangesToLabels(changes types.LabelChanges, labels types.Labels)

return mergedLabels, labelsToAdd, labelsToRemove
}

func addValue(mergedLabels types.Labels, change *types.LabelChange, value string, labelsToAdd types.Labels) {
found := false
for _, currentValue := range mergedLabels[change.Key] {
if currentValue == value {
found = true
break
}
}
if !found {
labelsToAdd[change.Key] = append(labelsToAdd[change.Key], value)
mergedLabels[change.Key] = append(mergedLabels[change.Key], value)
}
}
4 changes: 2 additions & 2 deletions pkg/query/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ var _ = Describe("Update", func() {
body, err := sjson.DeleteBytes(body, "labels.0.values")
Expect(err).ToNot(HaveOccurred())
changes, err := LabelChangesFromJSON(body)
Expect(err).To(HaveOccurred())
Expect(changes).To(BeNil())
Expect(err).ToNot(HaveOccurred())
Expect(changes).ToNot(BeNil())
})
})

Expand Down
3 changes: 2 additions & 1 deletion pkg/types/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ const (

// RequiresValues returns true if the operation requires values to be provided
func (o LabelOperation) RequiresValues() bool {
return o != RemoveLabelOperation
// add support for empty value
return o != RemoveLabelOperation && o != AddLabelOperation
}

// LabelChange represents the changes that should be performed to a label
Expand Down
2 changes: 1 addition & 1 deletion storage/postgres/constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ package postgres

// todo: get automatically from folder
// change this line with the latest version of the migrations:
const latestMigrationVersion = "20210808120000"
const latestMigrationVersion = "20211125100000"
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
BEGIN;

ALTER TABLE visibility_labels ALTER COLUMN val SET NOT NULL;
ALTER TABLE visibility_labels ADD CONSTRAINT visibility_labels_val_check CHECK (val <> '');
ALTER TABLE broker_labels ALTER COLUMN val SET NOT NULL;
ALTER TABLE broker_labels ADD CONSTRAINT broker_labels_val_check CHECK (val <> '');
ALTER TABLE platform_labels ALTER COLUMN val SET NOT NULL;
ALTER TABLE platform_labels ADD CONSTRAINT platform_labels_val_check CHECK (val <> '');
ALTER TABLE service_offering_labels ALTER COLUMN val SET NOT NULL;
ALTER TABLE service_offering_labels ADD CONSTRAINT service_offering_labels_val_check CHECK (val <> '');
ALTER TABLE service_plan_labels ALTER COLUMN val SET NOT NULL;
ALTER TABLE service_plan_labels ADD CONSTRAINT service_plan_labels_val_check CHECK (val <> '');
ALTER TABLE notification_labels ALTER COLUMN val SET NOT NULL;
ALTER TABLE notification_labels ADD CONSTRAINT notification_labels_val_check CHECK (val <> '');
ALTER TABLE service_instance_labels ALTER COLUMN val SET NOT NULL;
ALTER TABLE service_instance_labels ADD CONSTRAINT service_instance_labels_val_check CHECK (val <> '');
ALTER TABLE service_binding_labels ALTER COLUMN val SET NOT NULL;
ALTER TABLE service_binding_labels ADD CONSTRAINT service_binding_labels_val_check CHECK (val <> '');
ALTER TABLE broker_platform_credential_labels ALTER COLUMN val SET NOT NULL;
ALTER TABLE broker_platform_credential_labels ADD CONSTRAINT broker_platform_credential_labels_val_check CHECK (val <> '');

COMMIT;
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
BEGIN;

ALTER TABLE visibility_labels ALTER COLUMN val DROP NOT NULL;
ALTER TABLE visibility_labels DROP CONSTRAINT visibility_labels_val_check;
ALTER TABLE broker_labels ALTER COLUMN val DROP NOT NULL;
ALTER TABLE broker_labels DROP CONSTRAINT broker_labels_val_check;
ALTER TABLE platform_labels ALTER COLUMN val DROP NOT NULL;
ALTER TABLE platform_labels DROP CONSTRAINT platform_labels_val_check;
ALTER TABLE service_offering_labels ALTER COLUMN val DROP NOT NULL;
ALTER TABLE service_offering_labels DROP CONSTRAINT service_offering_labels_val_check;
ALTER TABLE service_plan_labels ALTER COLUMN val DROP NOT NULL;
ALTER TABLE service_plan_labels DROP CONSTRAINT service_plan_labels_val_check;
ALTER TABLE notification_labels ALTER COLUMN val DROP NOT NULL;
ALTER TABLE notification_labels DROP CONSTRAINT notification_labels_val_check;
ALTER TABLE service_instance_labels ALTER COLUMN val DROP NOT NULL;
ALTER TABLE service_instance_labels DROP CONSTRAINT service_instance_labels_val_check;
ALTER TABLE service_binding_labels ALTER COLUMN val DROP NOT NULL;
ALTER TABLE service_binding_labels DROP CONSTRAINT service_binding_labels_val_check;
ALTER TABLE broker_platform_credential_labels ALTER COLUMN val DROP NOT NULL;
ALTER TABLE broker_platform_credential_labels DROP CONSTRAINT broker_platform_credential_labels_val_check;

COMMIT;
15 changes: 14 additions & 1 deletion test/broker_test/broker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2571,7 +2571,20 @@ var _ = test.DescribeTestsFor(test.TestCase{
Status(http.StatusOK)
})
})

Context("Add label empty value", func() {
BeforeEach(func() {
operation = types.AddLabelOperation
changedLabelKey = "cluster_id"
changedLabelValues = []string{}
})
It("Should return 200", func() {
ctx.SMWithOAuth.PATCH(web.ServiceBrokersURL + "/" + id).
WithJSON(patchLabelsBody).
Expect().
Status(http.StatusOK).JSON().
Path("$.labels").Object().Keys().Contains(changedLabelKey)
})
})
Context("Remove a label", func() {
BeforeEach(func() {
operation = types.RemoveLabelOperation
Expand Down
4 changes: 3 additions & 1 deletion test/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"github.com/Peripli/service-manager/pkg/multitenancy"
"github.com/tidwall/gjson"
"reflect"
"time"

"github.com/Peripli/service-manager/pkg/util"
Expand Down Expand Up @@ -214,7 +215,8 @@ func MapContains(actual Object, expected Object) {
if !ok {
Fail(fmt.Sprintf("Missing property '%s'", k), 1)
}
if value != v {

if !reflect.DeepEqual(value, v) {
Fail(
fmt.Sprintf("For property '%s':\nExpected: %s\nActual: %s", k, v, value),
1)
Expand Down
35 changes: 35 additions & 0 deletions test/platform_test/platform_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,41 @@ var _ = test.DescribeTestsFor(test.TestCase{

By("Update is persisted")

reply = ctx.SMWithOAuth.GET(web.PlatformsURL + "/" + id).
Expect().
Status(http.StatusOK).JSON().Object()

common.MapContains(reply.Raw(), updatedPlatform)
})
It("when labels value are empty returns 200", func() {
By("Update platform")

updatedPlatform := common.MakePlatform("", "cf-11", "cff", "descr2")
delete(updatedPlatform, "id")
changeLabels := []*types.LabelChange{
{
Operation: types.AddLabelOperation,
Key: "newKey",
},
}
updatedPlatform["labels"] = changeLabels
reply := ctx.SMWithOAuth.PATCH(web.PlatformsURL + "/" + id).
WithJSON(updatedPlatform).
Expect().
Status(http.StatusOK).JSON().Object()

reply.NotContainsKey("credentials")
labels := map[string]interface{}{
"newKey": []interface{}{""},
}

updatedPlatform["labels"] = labels

updatedPlatform["id"] = id
common.MapContains(reply.Raw(), updatedPlatform)

By("Update is persisted")

reply = ctx.SMWithOAuth.GET(web.PlatformsURL + "/" + id).
Expect().
Status(http.StatusOK).JSON().Object()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ package service_test
import (
"context"
"fmt"
"github.com/Peripli/service-manager/operations"
"github.com/Peripli/service-manager/pkg/instance_sharing"
"github.com/Peripli/service-manager/pkg/query"
"strings"
"sync/atomic"
"time"

"github.com/Peripli/service-manager/operations"
"github.com/Peripli/service-manager/pkg/instance_sharing"
"github.com/Peripli/service-manager/pkg/query"

"github.com/Peripli/service-manager/pkg/env"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
Expand Down Expand Up @@ -627,6 +628,18 @@ var _ = DescribeTestsFor(TestCase{
WithJSON(postInstanceRequestTLS).
Expect().Status(http.StatusAccepted)
})
It("returns 201", func() {
EnsurePlanVisibility(ctx.SMRepository, TenantIdentifier, types.SMPlatform, servicePlanIDWithTLS, TenantIDValue)
labels := types.Labels{
"organization_guid": []string{},
}

postInstanceRequestTLS["labels"] = labels
ctx.SMWithOAuthForTenant.POST(web.ServiceInstancesURL).
WithQuery("async", false).
WithJSON(postInstanceRequestTLS).
Expect().Status(http.StatusCreated)
})

It("returns 201", func() {
EnsurePlanVisibility(ctx.SMRepository, TenantIdentifier, types.SMPlatform, servicePlanIDWithTLS, TenantIDValue)
Expand Down Expand Up @@ -668,7 +681,6 @@ var _ = DescribeTestsFor(TestCase{
JSON().Object().
Keys().Contains("error", "description")
})

Context("when request body contains multiple label objects", func() {
It("returns 400", func() {
ctx.SMWithOAuthForTenant.POST(web.ServiceInstancesURL).
Expand Down Expand Up @@ -2092,6 +2104,26 @@ var _ = DescribeTestsFor(TestCase{
Expect(method).To(Not(Equal("PATCH")))
})
})
When("only label is provided in request body- value is empty", func() {
It("returns success", func() {
labels := []*types.LabelChange{
{
Operation: types.AddLabelOperation,
Key: "labelKey1",
},
}
patchLabelsBody["labels"] = labels

testCtx.SMWithOAuthForTenant.PATCH(web.ServiceInstancesURL+"/"+SID).
WithQuery("async", "false").
WithJSON(patchLabelsBody).Expect().Status(http.StatusOK).JSON().Object()
// Expect to retrieve the data from the broker of the creat instance and not of the update instance
// method should not be patch to the broker, but only post of the previous request
method := brokerServer.LastRequest.Method
Expect(method).To(Not(Equal("PATCH")))

})
})
When("invalid label key", func() {
It("returns error", func() {
labels := []*types.LabelChange{
Expand Down

0 comments on commit 53c01a9

Please sign in to comment.