Skip to content

Commit

Permalink
[INTERNAL] ResourceTagCollection: Allow "super collections"
Browse files Browse the repository at this point in the history
  • Loading branch information
RandomByte committed Dec 2, 2021
1 parent 5b5f43e commit b4a20db
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 1 deletion.
26 changes: 25 additions & 1 deletion lib/ResourceTagCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,29 @@ const tagNamespaceRegExp = new RegExp("^[a-z][a-z0-9]*$"); // part before the co
const tagNameRegExp = new RegExp("^[A-Z][A-Za-z0-9]+$"); // part after the colon

class ResourceTagCollection {
constructor({allowedTags}) {
constructor({allowedTags, superCollection}) {
if (!allowedTags || !allowedTags.length) {
throw new Error(`Missing parameter 'allowedTags'`);
}

if (superCollection) {
this._superCollection = superCollection;
this._superTags = this._superCollection.getAcceptedTags();
} else {
this._superTags = [];
}

// No validation of tag names here since we might remove/ignore
// this parameter in the future and generally allow all tags
this._allowedTags = Object.freeze(allowedTags);
this._pathTags = {};
}

setTag(resource, tag, value = true) {
if (this._superTags.includes(tag)) {
return this._superCollection.setTag(resource, tag, value);
}

this._validateResource(resource);
this._validateTag(tag);
this._validateValue(value);
Expand All @@ -25,6 +37,10 @@ class ResourceTagCollection {
}

clearTag(resource, tag) {
if (this._superTags.includes(tag)) {
return this._superCollection.clearTag(resource, tag);
}

this._validateResource(resource);
this._validateTag(tag);

Expand All @@ -35,6 +51,10 @@ class ResourceTagCollection {
}

getTag(resource, tag) {
if (this._superTags.includes(tag)) {
return this._superCollection.getTag(resource, tag);
}

this._validateResource(resource);
this._validateTag(tag);

Expand All @@ -44,6 +64,10 @@ class ResourceTagCollection {
}
}

getAcceptedTags() {
return [...this._allowedTags, ...this._superTags];
}

_validateResource(resource) {
const path = resource.getPath();
if (!path) {
Expand Down
108 changes: 108 additions & 0 deletions test/lib/ResourceTagCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,114 @@ test("clearTag", (t) => {
"_validateTag called with correct arguments");
});

test("superCollection: setTag", (t) => {
const resource = new Resource({
path: "/some/path"
});
const superTagCollection = new ResourceTagCollection({
allowedTags: ["abc:MySuperTag"],
});
const tagCollection = new ResourceTagCollection({
allowedTags: ["abc:MyTag"],
superCollection: superTagCollection
});

const validateResourceSpy = sinon.spy(superTagCollection, "_validateResource");
const validateTagSpy = sinon.spy(superTagCollection, "_validateTag");
const validateValueSpy = sinon.spy(superTagCollection, "_validateValue");

tagCollection.setTag(resource, "abc:MySuperTag", "my super value");
tagCollection.setTag(resource, "abc:MyTag", "my value");

t.deepEqual(superTagCollection._pathTags, {
"/some/path": {
"abc:MySuperTag": "my super value"
}
}, "Super tag correctly stored");
t.deepEqual(tagCollection._pathTags, {
"/some/path": {
"abc:MyTag": "my value"
}
}, "Non-super tag correctly stored");

t.is(validateResourceSpy.callCount, 1, "_validateResource called once");
t.is(validateResourceSpy.getCall(0).args[0], resource,
"_validateResource called with correct arguments");

t.is(validateTagSpy.callCount, 1, "_validateTag called once");
t.is(validateTagSpy.getCall(0).args[0], "abc:MySuperTag",
"_validateTag called with correct arguments");

t.is(validateValueSpy.callCount, 1, "_validateValue called once");
t.is(validateValueSpy.getCall(0).args[0], "my super value",
"_validateValue called with correct arguments");
});

test("superCollection: getTag", (t) => {
const resource = new Resource({
path: "/some/path"
});
const superTagCollection = new ResourceTagCollection({
allowedTags: ["abc:MySuperTag"],
});
const tagCollection = new ResourceTagCollection({
allowedTags: ["abc:MyTag"],
superCollection: superTagCollection
});

tagCollection.setTag(resource, "abc:MySuperTag", 456);
tagCollection.setTag(resource, "abc:MyTag", 123);

const validateResourceSpy = sinon.spy(superTagCollection, "_validateResource");
const validateTagSpy = sinon.spy(superTagCollection, "_validateTag");

const value = tagCollection.getTag(resource, "abc:MySuperTag");

t.is(value, 456, "Got correct tag value");

t.is(validateResourceSpy.callCount, 1, "_validateResource called once");
t.is(validateResourceSpy.getCall(0).args[0], resource,
"_validateResource called with correct arguments");

t.is(validateTagSpy.callCount, 1, "_validateTag called once");
t.is(validateTagSpy.getCall(0).args[0], "abc:MySuperTag",
"_validateTag called with correct arguments");
});

test("superCollection: clearTag", (t) => {
const resource = new Resource({
path: "/some/path"
});
const superTagCollection = new ResourceTagCollection({
allowedTags: ["abc:MySuperTag"],
});
const tagCollection = new ResourceTagCollection({
allowedTags: ["abc:MyTag"],
superCollection: superTagCollection
});

tagCollection.setTag(resource, "abc:MySuperTag", 123);

const validateResourceSpy = sinon.spy(superTagCollection, "_validateResource");
const validateTagSpy = sinon.spy(superTagCollection, "_validateTag");

tagCollection.clearTag(resource, "abc:MySuperTag");

t.deepEqual(superTagCollection._pathTags, {
"/some/path": {
"abc:MySuperTag": undefined
}
}, "Tag value set to undefined");

t.is(validateResourceSpy.callCount, 1, "_validateResource called once");
t.is(validateResourceSpy.getCall(0).args[0], resource,
"_validateResource called with correct arguments");

t.is(validateTagSpy.callCount, 1, "_validateTag called once");
t.is(validateTagSpy.getCall(0).args[0], "abc:MySuperTag",
"_validateTag called with correct arguments");
});

test("_validateTag: Not in list of allowed tags", (t) => {
const tagCollection = new ResourceTagCollection({
allowedTags: ["abc:MyTag"]
Expand Down

0 comments on commit b4a20db

Please sign in to comment.