Installing NiFi on a MacBook

18 Dec 2017

Below, I documented the steps I had to take to install NiFi on my Mac using Homebrew:

I ran brew install nifi

Which resulted in this error: Homebrew must be run under Ruby 2.3! You're running 2.0.0. (RuntimeError)

So, I ran brew update-reset (as suggested by StackOverflow). That seemed to work.

I then ran brew install nifi and received this error:

Error: Xcode alone is not sufficient on Sierra.
Install the Command Line Tools:
  xcode-select --install

Obviously, I entered xcode-select --install and installed it. This took a few minutes.

Now trying brew install nifi again…

nifi: Java 1.8+ is required to install this formula.
JavaRequirement unsatisfied!
You can install with Homebrew-Cask:
 brew cask install java

Okay, running brew cask install java.

Now trying brew install nifi. Success! Nice!

Next up, try running NiFi via nifi run- I’m getting this error: WARN [main] org.apache.nifi.bootstrap.Command Launched Apache NiFi but could not determined the Process ID.

After some Googling, I determined that we need java8 for NiFi, not java9 (which Homebrew installs by default). You can check your java version with java --version.

You will need to take the following steps to delete java9 and switch to java8:

/usr/libexec/java_home -V – list all versions of Java on the machine

brew tap caskroom/versions – allow brew to lookup versions

brew cask install java8 – install java8 (if you haven’t already)

brew cask uninstall java – get rid of the default java9 (not strictly required)

export JAVA_HOME=$(/usr/libexec/java_home -v1.8) – set JAVA_HOME to java8

If you have completed all of the above steps, you should be able to now run nifi run and get something similar to below.

davisford$ nifi run

Java home: /Library/Java/JavaVirtualMachines/jdk1.8.0_152.jdk/Contents/Home
NiFi home: /usr/local/Cellar/nifi/1.4.0/libexec

...
...

INFO [main] org.apache.nifi.bootstrap.Command Launched Apache NiFi with Process ID 29854

We did it! You should be able to visit http://localhost:8080/nifi in your browser and get started.

Possible Issue: “JAVA_HOME not set; results may vary”

This warning occurs at the top of the output when using nifi run.

davisford$ nifi run
nifi: JAVA_HOME not set; results may vary
Java home:
NiFi home: /usr/local/Cellar/nifi/1.4.0/libexec

If you see the warning JAVA_HOME not set; results may vary when you use nifi run, you probably forgot to export JAVA_HOME in the above step.

Check your java8 installation location using /usr/libexec/java_home -V.

Update the JAVA_HOME var using export JAVA_HOME=$(/usr/libexec/java_home -v1.8).

Now run nifi run again and see if it works for you :)


A Jekyll Minification Script - in Bash

17 Dec 2017

Here’s a script to help you out when developing with Jekyll. I am very aware that perfectly good minification scripts exist for Jekyll - they are better and more flexible than mine, I’m sure. However, this is just a bash script (it does use some npm installs), and it’s pretty easy to configure.

I developed this while working on a couple of Jekyll sites (this one included). It is pretty handy.

It minifies your assets, compresses your images, and uploads it all to S3 for you. It can even optionally generate your favicon files for you. This blog ([daviseford.com](https://daviseford.com)) is run off an EC2 instance that syncs to my S3 bucket every couple of minutes, so all I need to do is upload my changes to S3, and an EC2 cron-job will take care of the rest. This blog is now run from an S3 bucket - fully static.

For my dad’s site, parkcenterautomotive.com, I use S3’s static site hosting capability, which makes the whole process extraordinarily simple.

I’ll show you how it looks for Park Center Automotive. All configuration of the script is done at the top of the file.

You can run this script with a -s flag to automatically install the npm dependencies (Google Closure Compiler, UglifyCSS, and HTML Minifier).

To use this script, create a blank file named upload.sh file in the root directory of your Jekyll site. Paste the above script into that file and save.

Make sure to configure your options at the top of the script!

Then run the script setup by typing sh upload.sh -s. Once those dependencies are pulled down, run sh upload.sh -i to begin compressing and optimizing your images and code.


ES2017 Javascript Module - Cryptopia API

16 Sep 2017

Here’s a file you can use to connect to the Cryptopia API.

This snippet allows you to programmatically access the Cryptopia API using Promises, which is much, much easier than dealing with callbacks, in my opinion. I generally do not release any crypto-related code, but in this case, I think I can help a few people out.

// Sample Usage
public_api('GetMarkets', {hours: 1}).then(res => console.log(res))

const iso_fetch = require('isomorphic-fetch');

function public_api(method, params = {}) {
    return new Promise((resolve, reject) => {
        try {
            const public_methods = [
                'GetCurrencies',
                'GetTradePairs',
                'GetMarkets',
                'GetMarket',
                'GetMarketHistory',
                'GetMarketOrders'
            ];
            const host_name = 'https://www.cryptopia.co.nz';
            let uri = '/Api/' + method;
            if (public_methods.includes(method)) {
                if (params) {
                    uri += "/" + Object.values(params).join('/');
                }
                iso_fetch(host_name + uri)
                    .then(res => res.json())
                    .catch(err => reject(err))
                    .then(res => resolve(res))
                    .catch(err => reject(err))
            } else {
                return reject(new Error(`${method} does not exist in the Cryptopia Public API!`))
            }
        } catch (e) {
            return reject(e)
        }
    })
}

module.exports = public_api;

ES5 JavaScript - Using Getters to create a self-aware object

25 Aug 2017

Let’s imagine you’re on a large project. You have the following limitation - ES5 Javascript.

Now, what happens in large codebases with 20k+ lines? They will end up with files called config.js and contact_info.js and environments.js, etc. Reference files that are frequently used.

In my case, our project has some code that (for example), shouldn’t run in production, but it should run in a development environment.

We had a file that looked like this:

const ENVs = {
    // Arrays of strings. We use the ENV=[environment] condition when running scripts.
    // E.G. our CI will run ENV=test node script.js
    is_dev: ['development', 'dev_server_2'],
    is_prod: ['production'],
    is_test: ['test', 'aws_test'],
    is_aws: ['aws_test'],
};
module.exports = ENVs;

So here’s how we typically would use this. Let’s say we don’t want a certain part of code to run if we’re in the production environment (a pretty common need).

Using Node.js to get the ENV environmental variable, we would check like this:

const environment = require('./environment.js')

const env = process.env.ENV; // Get the ENV environmental variable using Node

if (environment.is_prod.indexOf(env) > -1) {
    return; // end the script
}

// one liner. this is what ends up happening in real life
if (environment.is_prod.indexOf(process.env.ENV) > -1) return;

If you’re saying dude, just use .includes() - remember, ES5!


Okay, so let’s say we have an urge to make this more readable across the codebase. What’s one way to solve this?

Why, sure, let’s introduce some more overhead to this process! :)

Let’s modify that object we worked with earlier.

const ENVs = {
    dev: ['development', 'dev_server_2'],
    prod: ['production'],
    test: ['test', 'aws_test'],
    aws: ['aws_test'],

    get is() {
        // Utility lookup functions added here
    }
};

We’ve added a getter to the object called is. is is an object that will contain pre-computed responses about the environment we’re working in.

In the end, we want to be able to make a call like this: environment.is.dev. The logic for a self-aware object is as follows:

get is() {
    return Object.keys(this).filter(k => k !== 'is').reduce((accum, key) => {
        accum[key] = this[key].indexOf(process.env.ENV) > -1;
        return accum;
    }, {})
}

The whole thing ends up looking like this.

const ENVs = {
    dev: ['development', 'dev_server_2'],
    prod: ['production'],
    test: ['test', 'aws_test'],
    aws: ['aws_test'],
    get is() {
        return Object.keys(this).filter(k => k !== 'is').reduce((accum, key) => {
            accum[key] = this[key].indexOf(process.env.ENV) > -1;
            return accum;
        }, {})
    }
};

module.exports = ENVs;

Our developers can now do something easy when they’re trying to determine where the hell their code is running.

const env = require('./environment.js')

if (env.is.prod) {
    return; // don't run in prod!!!
}
if (env.is.dev || env.is.test) {
    // do dev or test stuff
}

This sort of self-aware object makes working with constant data much simpler. If you know a cleaner way to do this, email me :) I’ll give you a prize. The prize is me sending you an email back btw.