Skip to content

emil0r/porter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

64 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

porter

porter

babashka library for creating config files

You have lots of configuration files that needs to be generated based on input. The input is spread over multiple files and changes depending on what environment you’re producing the config files for. You end up using Makefile (good) and bash/python/ruby/insert-here and question your life choices.

You can now use porter and still question your life choices. But at least it’ll be in EDN and Babashka.

Usage

  • build-output takes [env, src, opts, ctx-paths] as arguments

    • env is required can be things like :local, :staging, :production, etc

    • src is the source input in the form of a string or a file

    • opts is a map with optional keys :dest, :print, :namespaces, :classpaths, :exec and :injections

    • ctx-paths is the context to be read from files to be put into the src

Example usage
(build-output :test "{{:test-data}}" {} ["build-resources/config.test.edn"])

opts

  • :dest - if we wish to send the output to a destination file

  • :print - if we wish to have the output printed to stdout

  • :print-ctx - if we wish to have the context map printed to stdout

  • :print-injections - if we wish to have the injection map printed to stdout

  • :namespaces - for evaling in ctx-paths

  • :classpaths - classpaths to add to the library. Used for the SCI interpreter

  • :injections - a map which will be merged with the context map

  • :exec - do we wish to execute the src as a command in a shell

ctx-paths

ctx-paths are deep-merged into each other, starting from the first entry.

context (ctx)

When the context is created, a recursive lookup (up to 30 degrees) is done, allowing for building up a complete hashmap with all data required for building the output.

It’s possible to manually skip processing by adding ^:skip as a metadata in front of any element inside the EDN ctx map. Main use is when you wish to protect arguments sent in to ctx functions from being processed (as lookup vectors).

Lookup via vectors in ctx
{:client/name "client-vip-name"
 :image.name/platform "platform"
 :version "1.0"
 :docker {:production {:platform {:image-namespace [:client/name]
                                  :image-name      [:image.name/platform]
                                  :tag             [:version]}}}}

The above would produce the following output being run through build-output

Output from lookup via vectors
{:client/name "client-vip-name"
 :image.name/platform "platform"
 :version "1.0"
 :docker {:production {:platform {:image-namespace "client-vip-name"
                                  :image-name "platform"
                                  :tag "1.0"}}}}

ctx functions

It’s also possible to use functions in the context files to build the output. Porter supports the user namespace by default. Anything else has to be provided.

The user namespace has a ctx var injected into the SCI context and holds the context map created from ctx-paths.

The ctx var has the env var injected under the :env key and can be refered to as a key in the map.

Example usage
;; source code for get-namespace+tag in 'example-ns

(defn get-namespace+tag [ns n tag]
  (format "%s.%s:%s" ns n tag))

;; config.test.edn

{:client/name "client-vip-name"
 :image.name/platform "platform"
 :version "1.0"
 :docker {:production {:platform {:image-namespace [:client/name]
                                  :image-name [:image.name/platform]
                                  :tag [:version]}}}
 :docker.image/platform+tag (example-ns/get-namespace+tag
                              [:docker [:env] :platform :image-namespace]
                              [:docker [:env] :platform :image-name]
                              [:docker [:env] :platform :tag])}

(build-output :test
              "config.test.edn"
              {:print true
               :classpaths ["classpath-example"]
               :namespaces ['example-ns]}
              ["build-resources/config.test.edn"])
=> {:client/name "client-vip-name"
    :image.name/platform "platform"
    :version "1.0"
    :docker {:production {:platform {:image-namespace "client-vip-name"
                                     :image-name "platform"
                                     :tag "1.0"}}}
    :docker.image/platform+tag "client-vip-name.platform:1.0"}

src paths

When referring paths from ctx in src there are two options available.

  • {{:my.path/here}} - this is equalivent to a Clojure keyword

  • {{[:my :path :here]}} - this is equalivent to a Clojure vector

Both options are paths to the context where data can be found.

porter CLI tool

There is a porter CLI tool which automatically downloads and uses this library via the command line.

curl -o /usr/local/bin/porter https://raw.githubusercontent.com/emil0r/porter/refs/heads/master/porter
chmod +x /usr/local/bin/porter
Example usage from local testing
./porter --env :local \
       --src "dev-resources/test.tester.yml" \
       --ctx-paths "dev-resources/test.tester.edn" \
       --print true \
       --dest testus.yml \
       --injections '{:version "1.0.0"}' \
       --classpaths "clj" \
       --namespaces tester

Gives the following output.

  • Adding classpath 'clj' is from the classpath specified

  • Requiring tester is a namespace used

  • This is from tester 1.0.0 is from a function called from the tester namespace

  • Invalid input gives output of either empty paths or broken paths for the src file

    • Empty paths and Broken paths will be colored red with a white background

Adding classpath 'clj'
Requiring tester
This is from tester 1.0.0
Invalid input
Empty paths #{[:infra :local :postgres :user] [:infra :local :postgres :password]}, :broken-paths #{}
Options
porter --help

-- Options --

  --namespaces       Namespaces to add
  --print-injections Print injections to stdout
  --injections       Map of injections to the context map
  --exec             Execute the src as a shell command
  --src              Source of input. String or file. Can be multiple lines which will be joined together with a newline in between each entry. This is meant mainly for exec (blame Make)
  --env              Which environment are we using
  --classpaths       Classpaths to add
  --print            Print the output to stdout
  --print-ctx        Print ctx map to stdout
  --ctx-paths        vector of strings to context edn files
  --dest             Which file to write the output to

Example

There is a basic example of how to use porter in the example directory.

Create the config file
cd example

make ENV=:production build-config-files-service

make ENV=:production build-docker-anchorpoint

About

CLI tool/libary for creating config files

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published