Domain Driven Architecture

July 28, 2017 By: Michael Jerger

dda-pallet series: 2-Compose Crates

Our Goal is a proper set up development environment straight away from beginning - but also be able to adjust your setup as you like it. We are using dda-pallet to describe this infrastructure as clojure code. This Blog is part of the "dda-pallet" series and will show step by step how to setup a clojure ide:

  1. Provision existing Targets
  2. Compose crates
  3. Convention over Configuration
  4. Execute Pallet local
  5. Plugin Operational Services
  6. TestDriven DevOps

Last time we created a user and git repositories in our future ide. Today we will think about the many small tools, making a vm working smooth. If we're able to automate fine grained tool installation, it would be easy to setup a new vm an continue working seamless.

While installing vm basics we will learn how to compose two dda-pallet modules (we call them crate):

As result our virtual machine should have a user "user-name" installed and this user should find some checked out git repositories in user home:

Get dda-git-crate

Lets start and clone the dda-git-crate:

  1. Clone dda-git-crate repository from GitHub
    git clone -b dda-git-crate-0.1.2
  2. Open "instantiate_existing.clj" located in:

Preconditions & User-Configuration

We have the same preconditions as last time. We will start from a clean virtual machine having xubuntu 16.4.2LTS and ssh-server installed. Keep the credentials on your mind for first time provisioning. Now let's put these informations into the "instantiate-existing" name-space:

  1. Adjust your target ip (if we type ifconfig in virtual machine we will find our IP - in our case)
    (def provisioning-ip "")
  2. Fill in your provision user credentials (if you've chosen on vm-setup the same credentials as we did, go with "initial - secure1234". If not, replace with yours)
    (def provisioning-user
     {:login "initial"
      :password "secure1234"})
  3. Adjust authorized-keys for the user ("user-name") we will create in order to be able to connect by ssh:
    (def ssh-pub-key
      {:type "ssh-rsa"
       :public-key "AAAAB....."
       :comment "user-names-key"})
    (def user-config
     {:user-name {:hashed-password  "xxx"
      :authorized-keys [ssh-pub-key]}})

You can find a more detailed description how-to create vm and configure user in series first post.

Git Configuration

The section "git-config" contains our configuration for the installation of git and selected git repositories:

(def git-config
  {:os-user :user-name
   :user-email ""
   :repo-groups #{:dda-pallet}})
Where as

  • :os-user defines for which user git should be configured
  • :user-email is input for user global git configuration and
  • :repo-groups defines, which repositories should be cloned.

You will find a more detailed definition of repo-groups in "domain.clj" located in:


The declared repo group is defined as:

(def dda-projects

Provision your Virtual Machine

Now it's time to bring our configuration to our virtual machine:

  1. Start your REPL & switch to the instantiate-existing namespace
    (use '
  2. Start provisioning
    your REPL should look somewhat as follows: In case of success, your REPL will show:

Inspect your virtual machine

Successfully we finished provisioning. So let's test the newly provisioned user. We should be able to connect via ssh:

 ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no user-name@
You should now find the cloned repositories in folder ~/code/dda-pallet:

Find out how composition of crates is realized

For some deeper insights let's have a look at the composition of crates in dda-pallet. Composition of dda-pallet crates is done at three levels:

  1. project.clj: In project.clj we typically define our dependencies. Every crate is available as versioned jar on clojars. In our case we use the composition only for integration testing, so you will find dda-user-crate in the dev profile:
       [dda/dda-user-crate "0.5.0"]
  2. group-spec: A group-spec defines server-types e.g. "A ide-installation consists of dda-users-crate, dda-git-crate, dda-managed-vm crate, dda-managed-ide crate and dda-backup-crate". A group-spec describes statically what should be applied in general. In context of dda-git-crate take a look at integration/dda/pallet/dda_git_crate/app/user_app.clj name-space you will find the git-group-spec:
    (s/defn ^:always-validate git-group-spec
       app-config [(config-crate/with-config app-config)
    This denotes that the dda-git-crate consist of a configuration, users and git. By convention each dda-pallet crate exposes with-user or with-git to make composition easy.
  3. configuration: While the group-spec defines the type, the configuration defines the instance. You will find the composition of configurations in the same name-space:
    (defn app-configuration [git-config user-config]
        (user/app-configuration user-config :group-key :dda-git-group)
        (app/app-configuration git-config :group-key :dda-git-group)))
    Configurations are plain data. In order to compose configuration we use deep-merge over each crates configuration map. As configuration is plain data, you can inspect this function on your REPL and find out, how your composed configuration looks like.

Processes and Phases in dda-pallet

On inspecting results in the REPL you maybe wondering about terms like apply-install, apply-config, server-test or init, install or configure phases. Phases are building blocks for our provisioning processes. In dda-pallet we use the following phases:

  • bootstrap: Bootstrap is a convention originate from pallet. In this phase we bring up new compute services and other cloud resources.
  • settings: Settings is a convention originate from pallet. The settings phase collects informations from server nodes (we name these informations facts) without providing side effects. So the settings phase does not alter the state of servers nodes.
  • init: Init is a dda-pallet convention. Init brings nodes to a similar starting position (e.g. across different providers). In effect the following provisioning steps will be more standardized.
  • install: Install is a dda-pallet convention. The install phase brings software to nodes. The installation is intended to take effect only once.
  • configure: Configure is a convention originate from pallet. Configure brings the defined configuration to the target nodes. Configure is intended to be applied many times (at least every timy you change your configuration) and will overwrite existing changes.
  • app-rollout: App-Rollout is a dda-pallet convention. The app-rollout phase allows to execute manual steps and is used e.g.for migrations ore more complex roll outs. The app rollout phase supports automated preparation of manual roll out (e.g. download new application binaries, drivers, database migration scripts upfront).
  • test: Test is a dda-pallet convention. The test phase is used for comparing facts collected during the settings phase against given expectations. The test phase has no side effects on the target node.

In contrast apply-install, apply-config or server-test are predefined processes:

  • apply-install: applies settings, init, install and configure.
  • apply-config: applies settings and configure.
  • server-test: applies settings and test.

Tags: dda-managed-vm howto DomainDrivenDesign clojure ide composition dda-pallet provision existing target

Powered by Cryogen | Free Website Template by Download Website Templates | Impressum