Skip to content

Commit

Permalink
Merge pull request #1 from cf-platform-eng/add-satisfied-field
Browse files Browse the repository at this point in the history
Change how results are handled and passed up the chain:
  • Loading branch information
Pete Wall authored Aug 5, 2019
2 parents 4298595 + f0bc142 commit 9b101db
Show file tree
Hide file tree
Showing 20 changed files with 172 additions and 127 deletions.
2 changes: 1 addition & 1 deletion features/checking_needs.feature
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Feature: Checking needs
And a need is unsatisfied
When I check the needs
Then the needs check fails
And I see all of the needs
And I see all of the needs showing the unsatisfied need

Scenario: Unsatisfied needs file with --satisfied
Given a needs file
Expand Down
10 changes: 7 additions & 3 deletions features/step_definitions/check_steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ Then("I don't see any needs", function () {
})

Then("I see the satisfied need", function () {
assert.equal(this.stdout, "[{\"type\":\"environment_variable\",\"name\":\"MY_ENVIRONMENT_VARIABLE_1\"}]")
assert.equal(this.stdout, "[{\"type\":\"environment_variable\",\"names\":[\"MY_ENVIRONMENT_VARIABLE_1\"],\"satisfied\":true}]")
})

Then("I see the unsatisfied need", function () {
assert.equal(this.stdout, "[{\"type\":\"environment_variable\",\"name\":\"MY_ENVIRONMENT_VARIABLE_2\"}]")
assert.equal(this.stdout, "[{\"type\":\"environment_variable\",\"names\":[\"MY_ENVIRONMENT_VARIABLE_2\"],\"satisfied\":false}]")
})

Then("I see all of the needs", function () {
assert.equal(this.stdout, "[{\"type\":\"environment_variable\",\"name\":\"MY_ENVIRONMENT_VARIABLE_1\"},{\"type\":\"environment_variable\",\"name\":\"MY_ENVIRONMENT_VARIABLE_2\"}]")
assert.equal(this.stdout, "[{\"type\":\"environment_variable\",\"names\":[\"MY_ENVIRONMENT_VARIABLE_1\"],\"satisfied\":true},{\"type\":\"environment_variable\",\"names\":[\"MY_ENVIRONMENT_VARIABLE_2\"],\"satisfied\":true}]")
})

Then("I see all of the needs showing the unsatisfied need", function () {
assert.equal(this.stdout, "[{\"type\":\"environment_variable\",\"names\":[\"MY_ENVIRONMENT_VARIABLE_1\"],\"satisfied\":true},{\"type\":\"environment_variable\",\"names\":[\"MY_ENVIRONMENT_VARIABLE_2\"],\"satisfied\":false}]")
})
29 changes: 18 additions & 11 deletions lib/needs/aggregate.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ let Types = require("../types.js")
class Aggregate extends Need {
constructor(schema, input, types) {
super(schema, input)
types = types || new Types()

this.types = types || new Types()
this.needs = []
for (let need of input.needs) {
if (!this.types.has(need.type)) {
if (!types.has(need.type)) {
throw new Need.ValidationError("Invalid need", `Need type "${need.type}" does not exist`)
}

let type = this.types.get(need.type)
let type = types.get(need.type)
this.needs.push(new type(need))
}
}
Expand All @@ -28,14 +28,9 @@ class Aggregate extends Need {
}

Promise.all(promises.map(x => x.promise)).then(values => {
let satisfiedNeeds = promises.filter((elem, index) => values[index].satisfied).map(elem => elem.need)
let unsatisfiedNeeds = promises.filter((elem, index) => !values[index].satisfied).map(elem => elem.need)
resolve({
need: this,
satisfied: this.isSatisfied(unsatisfiedNeeds.length),
satisfiedNeeds,
unsatisfiedNeeds
})
let unsatisfiedCount = values.map(need => need.satisfied ? 0 : 1).reduce((val, total) => val + total, 0)
this.satisfied = this.isSatisfied(unsatisfiedCount)
resolve(this)
}).catch(reason => {
reject({
need: this,
Expand All @@ -44,6 +39,18 @@ class Aggregate extends Need {
})
})
}

filter(field, value) {
return this.needs.filter(need => need[field] == value)
}

getSatisfiedNeeds() {
return this.filter("satisfied", true)
}

getUnsatisfiedNeeds() {
return this.filter("satisfied", false)
}
}

module.exports = Aggregate
43 changes: 20 additions & 23 deletions lib/needs/binary.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ let Need = require("./need.js")
class Binary extends Need {
constructor(input) {
super(schema, input)
if (input.name) {
this.name = input.name
}
if (input.path) {
this.path = input.path
}
this.isExecutable = require("isexe")
this.which = require("which")
}
Expand All @@ -34,23 +40,19 @@ class Binary extends Need {
return this.which(binaryName, (err, path) => {
if (err && err.code == "ENOENT") {
debug(`"${binaryName}" does not exist`)
return resolve({
need: this,
satisfied: false
})
this.satisfied = false
return resolve(this)
} else if (err) {
debug(`Failed to check "${binaryName}"`)
return reject({
need: this,
reason: "failed to find executable binary"
})
}
let result = path != null
debug(`"${binaryName}" was ${result ? "found" : "not found"}`)
return resolve({
need: this,
satisfied: result
})

this.satisfied = path != null
debug(`"${binaryName}" was ${this.satisfied ? "found" : "not found"}`)
return resolve(this)
})
})
}
Expand All @@ -61,10 +63,8 @@ class Binary extends Need {
this.isExecutable(binaryPath, (err, executable) => {
if (err && err.code == "ENOENT") {
debug(`"${binaryPath}" does not exist`)
return resolve({
need: this,
satisfied: false
})
this.satisfied = false
return resolve(this)
} else if (err) {
debug(`Failed to check path "${binaryPath}"`)
return reject({
Expand All @@ -73,21 +73,18 @@ class Binary extends Need {
})
}

let result = Boolean(executable)
debug(`"${binaryPath}" exists and ${result ? "is" : "is not"} executable`)
return resolve({
need: this,
satisfied: result
})
this.satisfied = Boolean(executable)
debug(`"${binaryPath}" exists and ${this.satisfied ? "is" : "is not"} executable`)
return resolve(this)
})
})
}

check() {
if (this.data.name) {
return this.checkByName(this.data.name)
if (this.name) {
return this.checkByName(this.name)
} else {
return this.checkByPath(this.data.path)
return this.checkByPath(this.path)
}
}
}
Expand Down
12 changes: 5 additions & 7 deletions lib/needs/environment_variable.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ let Need = require("./need.js")
class EnvironmentVariable extends Need {
constructor(input) {
super(schema, input)
this.names = [...this.data.names || []]
if (this.data.name) {
this.names.push(this.data.name)
this.names = [...input.names || []]
if (input.name) {
this.names.push(input.name)
}
}

Expand All @@ -46,10 +46,8 @@ class EnvironmentVariable extends Need {
}
return result
}).reduce((result, value) => result && value, true)
return Promise.resolve({
need: this,
satisfied
})
this.satisfied = satisfied
return Promise.resolve(this)
}
}

Expand Down
23 changes: 7 additions & 16 deletions lib/needs/file.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,24 @@ class File extends Need {
constructor(input) {
super(schema, input)
this.glob = require("glob")
this.path = input.path
}

check() {
debug(`Looking for "${this.data.path}"...`)
debug(`Looking for "${this.path}"...`)
return new Promise((resolve, reject) => {
this.glob(this.data.path, (err, files) => {
this.glob(this.path, (err, files) => {
if (err) {
debug(`encountered an error looking for "${this.data.path}"`)
debug(`encountered an error looking for "${this.path}"`)
return reject({
need: this,
reason: "failed to check for file"
})
}

if (files.length == 0) {
debug(`"${this.data.path}" does not exist`)
return resolve({
need: this,
satisfied: false
})
}

debug(`"${this.data.path}" exists`)
resolve({
need: this,
satisfied: true
})
this.satisfied = files.length > 0
debug(`"${this.path}" ${this.satisfied ? "does" : "does not"} exist`)
return resolve(this)
})
})
}
Expand Down
9 changes: 4 additions & 5 deletions lib/needs/need.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@ class Need {
constructor(schema, input) {
let ajv = new Ajv()
this.validator = ajv.compile(schema)
this.data = input

return this.validate()
return this.validate(input)
}

validate() {
let valid = this.validator(this.data)
validate(input) {
let valid = this.validator(input)
if (!valid) {
throw new Need.ValidationError(`data for type "${this.constructor.type}" is not valid`, this.validator.errors)
}
this.type = input.type
}

check() {
Expand Down
6 changes: 3 additions & 3 deletions needs.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const types = new Types()
const And = types.get("and")

function needsToJSON(needs) {
return JSON.stringify(needs.map((need) => need.data))
return JSON.stringify(needs)
}

async function loadNeedsFromFile(file) {
Expand Down Expand Up @@ -92,9 +92,9 @@ async function run() {
}

if (argv.satisfied) {
console.log(needsToJSON(result.satisfiedNeeds))
console.log(needsToJSON(result.getSatisfiedNeeds()))
} else if (argv.unsatisfied) {
console.log(needsToJSON(result.unsatisfiedNeeds))
console.log(needsToJSON(result.getUnsatisfiedNeeds()))
} else {
console.log(needsToJSON(needs.needs))
}
Expand Down
12 changes: 10 additions & 2 deletions needs.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,16 @@
"type": "file",
"path": "/Users/pwall/src/cf-platform-eng/needs/needs.json"
}, {
"type": "file",
"path": "/this/file/does/not/exist"
"type": "or",
"needs": [
{
"type": "file",
"path": "/this/file/does/not/exist"
}, {
"type": "file",
"path": "*.json"
}
]
}, {
"type": "binary",
"name": "om"
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
"name": "needs",
"version": "0.1.0",
"description": "",
"license": "MIT",
"repository": "https://github.com/cf-platform-eng/needs",
"main": "needs.js",
"scripts": {
"build": "pkg . --targets latest-linux-x64,latest-macos-x64 --out-path ./build",
Expand Down
6 changes: 4 additions & 2 deletions spec/helpers/needs/always_broken.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
let Need = require("../../../lib/needs/need.js")
class AlwaysBroken extends Need {
constructor(input) {
super({}, input)
constructor() {
super({}, {
type: AlwaysBroken.type
})
}

check() {
Expand Down
12 changes: 6 additions & 6 deletions spec/helpers/needs/always_happy.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
let Need = require("../../../lib/needs/need.js")
class AlwaysHappy extends Need {
constructor(input) {
super({}, input)
constructor() {
super({}, {
type: AlwaysHappy.type
})
}

check() {
return Promise.resolve({
need: this,
satisfied: true
})
this.satisfied = true
return Promise.resolve(this)
}
}

Expand Down
6 changes: 2 additions & 4 deletions spec/helpers/needs/always_happy_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ describe("AlwaysHappy", function () {
describe("check", function () {
it("always resolves to true", async function () {
let need = new AlwaysHappy()
await expectAsync(need.check()).toBeResolvedTo({
need,
satisfied: true
})
await expectAsync(need.check()).toBeResolvedTo(need)
expect(need.satisfied).toBe(true)
})
})
})
12 changes: 6 additions & 6 deletions spec/helpers/needs/always_sad.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
let Need = require("../../../lib/needs/need.js")
class AlwaysSad extends Need {
constructor(input) {
super({}, input)
constructor() {
super({}, {
type: AlwaysSad.type
})
}

check() {
return Promise.resolve({
need: this,
satisfied: false
})
this.satisfied = false
return Promise.resolve(this)
}
}

Expand Down
6 changes: 2 additions & 4 deletions spec/helpers/needs/always_sad_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ describe("AlwaysSad", function () {
describe("check", function () {
it("always resolves to false", async function () {
let need = new AlwaysSad()
await expectAsync(need.check()).toBeResolvedTo({
need,
satisfied: false
})
await expectAsync(need.check()).toBeResolvedTo(need)
expect(need.satisfied).toBe(false)
})
})
})
Loading

0 comments on commit 9b101db

Please sign in to comment.