Pumlhorse
- PUML (Promise-driven Utility Modeling Language)
- Horse (Equus caballus)
Pumlhorse is a utility for creating readable and reusable scripts.
For a complete reference, visit pumlhorse.com
- Writing scripts
Specification
name: Introduction to Pumlhorsedescription: This is a basic script that writes some messagessteps: - log: Hello! - log: Goodbye!
Parameters
name: Use parametersdescription: Pass some parameters to those stepssteps: - sayGreeting: text: Hello, and welcome to Pumlhorse! - sayGoodbye: language: French text: Au revoir!
Variables
name: Pass variablesdescription: Set and use variables from your stepssteps: - myName = John Smith - sayGreeting: text: Hello, my name is $myName
name: Assign step results to variablessteps: #getMyName is a function that returns a string - myName = getMyName - sayGreeting: text: Hello, my name is $myName
name: Use complex objects in variablessteps: #getMyInfo is a function that returns { name: 'John Smith' } - myInfo = getMyInfo - sayGreeting: text: Hello, my name is $myInfo.name
name: Create complex objects as variablessteps: - myInfo = value: name: John Smith age: 34 - sayGreeting: text: Hello, my name is $myInfo.name
Inline Javascript
name: Use JavaScript inlinesteps: - myMixedCase = aBcDeFg - myLowerCase = $myMixedCase.toLowerCase() #myLowerCase is now 'abcdefg'
name: Declare JavaScript functions inlinefunctions: getMyInfo: return { name: 'John Smith', age: 25 } logMyInfo: # list parameters first - age - name # list function body last - this.log('My name is ' + name + ' and I am ' + age + ' years old')steps: - myInfo = getMyInfo - logMyInfo: name: $myInfo.name age: $myInfo.age # logs "My name is John Smith and I am 25 years old"
Conditionals
name: Simple if/then examplefunctions: getTodaysDate: - return new Date().getDay()steps: - dayOfWeek = $getTodaysDate() - if: value: ${ dayOfWeek == 5 } is true: - log: Congratulations, today is Friday! is false: - if: value: ${ dayOfWeek == 6 || dayOfWeek == 0} is true: - log: Congratulations, it's the weekend! is false: - log: Hang in there, you'll make it to the weekend!
Loops
name: Run some things a few timessteps: - loopTimes = 14 - repeat: times: $loopTimes steps: - log: Starting loop # do loop steps - log: Ending loop
name: Loop through items in a listfunctions: getLoopItems: return ["a", "b", "c"]steps: - items = getLoopItems - for: each: item in: $items steps: - log: Working with the letter $item - doLoopTasks: $item
name: Run a loop with varying datafunctions: doLogin: - username - password - this.log('Login with ' + username + ':' + password)steps: - scenarios: base: # (optional) provides a base set of values for every scenario username: jsmith cases: bad password: password: abadpassword good password: password: aBeTTerPassw0rd! steps: - doLogin: username: $username password: $password #Performs doLogin for "bad password" and "good password" scenarios
Logging
name: Basic logging functionssteps: - log: Here's a simple log message - warn: Something might be wrong - error: Something is definitely wrong!
name: Pass parameters to logging callssteps: - myFavoriteNumber = 42 - warn: Every tech thing has to have a $myFavoriteNumber reference
Assertions
name: Use assertionssteps: # all of these assertions succeed - isTrue: ${5 == 7 - 2} - isFalse: ${Math.PI == 3} - isNull: $fhqwhgads # Variable doesn't exist - isNotNull: 42 - areEqual: expected: men actual: ${"women".substr(2)} - areEqual: expected: game: horseshoe actual: game: horseshoe another: handgrenades partial: true # Only properties in expected value will be checked in actual value - areNotEqual: expected: free as in beer actual: free as in speech - isEmpty: ${[]} - isNotEmpty: ${[3, 4, 5]} - contains: array: - 4 - 5 - 6 value: 6 - contains: array: - game: horseshoe another: handgrenades value: game: horseshoe partial: true
HTTP Methods
name: Use HTTP methodssteps: - findUserResult = http.get: url: http://www.tempuri.org/api/findUser data: search: jsmith page: 2 # Issues GET request to http://www.tempuri.org/api/findUser?search=jsmith&page=2 - log: $findUserResult.json.username # Logs 'username' property of the JSON response body (requires the content-type to be application/json or text/json) - postResult = http.post: url: http://www.tempuri.org/api/createUser data: firstName: John lastName: Smith headers: Authorization: bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyaWQiOjQyLCJ1c2VybmFtZSI6ImVhc3Rlci5lZ2cifQ.U4nejjGFvXSERKtVWrgXXytXqe9oqdg8ws1AyLCp 4o0 # Issues POST request to http://www.tempuri.org/api/createUser with a JSON request of { "firstName": "John", "lastName": "Smith" } - http.isOk: $postResult # Asserts that the response was a 200 - log: $postResult.body #body contains the string content in the response # put, delete, patch, head, and options are also available
Timers
name: Wait for an amount of timesteps: - wait: milliseconds: 23 seconds: 45 - log: Well that was kinda long # Waits for 45.023 seconds - wait: minutes: 60 hours: 3 # Waits for four hours...use at your own discretion - log: Is anyone even here anymore?
name: See how long we waitedfunctions: doLongRunningProcess: - return this.wait(2000)steps: - timer1 = startTimer - doLongRunningProcess - stopTimer: $timer1 - log: That took $timer1.seconds seconds
Parallel tasks
name: Run multiple steps in parallelsteps: - parallel: - postUpdateToFacebook: This is my new status! - postUpdateToTwitter: This is my new tweet! - postUpdateToInstagram: This is a picture of my cat!functions: postUpdateToFacebook: - status - return this.wait(Math.random() * 1000).then(() => this.log('Updated status to ' + status)) postUpdateToTwitter: - tweet - return this.wait(Math.random() * 1000).then(() => this.log('Added new tweet:' + tweet)) postUpdateToInstagram: - caption - return this.wait(Math.random() * 1000).then(() => this.log('Added new picture with caption:' + caption))
Helpers
Some miscellaneous helpers
JSON serialization
name: Convert from string to objectfunctions: getObject: return { prop: 43 }steps: - obj = getObject - jsonString = toJson: $obj - log: $jsonString #logs "{prop:43}" - newObj = fromJson: $jsonString - log: $newObj.prop #logs "43"