Liking cljdoc? Tell your friends :D

dda-serverspec-crate

Clojars Project Build Status

Slack | DevOps Hacking with Clojure Meetup DevOps Hacking with Clojure | Website & Blog

Jump to

Local-remote-testing Usage Additional-info-about-the-configuration Targets-config-example Serverspec-config-example Reference-Targets Reference-Domain-API Reference-Infra-API Compatibility License

Features

The dda-serverspec-crate allows you to specify expected state for target-systems and test against their current state. dda-serverspec-crate provides tests for:

  • execution against localhost, remote hoste or multiple remote hosts.
  • files or folders presence / absence, plus specific FilePermissions/group/owner.
  • packages are installed / uninstalled
  • services listening to ip & port
  • validity of local certificate files
  • validity of certificates by https - maybe remote or localhost.
  • network connectivity to remote systems

Local-remote-testing

There are two modes of testing targets, either local or remote. Local tests are executed on the system the jar is running on. Local tests are executed by the current user.

ServerSpecLocalWhitebox

Remote tests are collection state (we name it facts) from target system on compare these facts against expectation on the system executing the dda-serverspec jar. Facts are collected via ssh & bash. Test utils, needed, can be installed by using the installation phase (use --install-dependencies on the command line).

ServerSpecRemoteWhitebox

Usage

  1. Download the jar-file from the releases page of this repository (e.g. curl -L -o serverspec.jar https://github.com/DomainDrivenArchitecture/dda-serverspec-crate/releases/download/1.1.1/dda-serverspec-crate-1.1.1-standalone.jar)
  2. Create the serverspec.edn configruration file in the same folder where you saved the jar-file. The serverspec.edn file specifies the tests that are performed against the server(s). You may use the following example as a starting point and adjust it according to your own needs:
{:netstat [{:process-name "sshd" :port "11" :running? false}  ;check if sshd is NOT running on port 11
           {:process-name "sshd" :port "22" :exp-proto "tcp6" :ip "::"}]      ;check if sshd is running on port 22 with the given config
 :file [{:path "/root/.bashrc"}                                               ;check if file exists
        {:path "/etc"}                                                        ;check if folder exists
        {:path "/absent" :exist? false}                                       ;check if file doesn't exists
        {:path "/root/.profile" :mod "644" :user "root" :group "root"}        ;check if file exists and has the given config
        {:path "/etc/resolv.conf" :link-to "../run/resolvconf/resolv.conf"}]  ;check if link exists and has the given target
 :netcat [{:host "www.google.com" :port 80}          ;check if host is reachable
          {:host "www.google.c" :port 80 :reachable? false}]
 :package [{:name "test" :installed? false}          ; check if package test is NOT installed
           {:name "nano"}]                           ; check if package nano is installed
 :http [{:url "https://domaindrivenarchitecture.org" ;provide full url
         :expiration-days 15}]}                      ; check if certificate of url is at least 15 days valid
  1. (optional) If you want to perform the tests on a remote server, please create additionally a targets.edn file. In this file you define gainst which server(s) the tests are performed and the corresponding login information. You may use and adjust the following example config:
{:existing [{:node-name "target1"                      ; semantic name (keep the default or use a name that suits you)
             :node-ip "192.168.56.104"}]               ; the ip4 address of the machine to be provisioned
             {:node-name "target2"                     ; semantic name (keep the default or use a name that suits you)
                          :node-ip "192.168.56.105"}]  ; the ip4 address of the machine to be provisioned
 :provisioning-user {:login "initial"                  ; user on the target machine, must have sudo rights
                     :password {:plain "secure1234"}}} ; password can be ommited, if a ssh key is authorized
  1. (optional) If you want to ensure, that certain test tools (like netcat or netstat) are present on the target system, you can once use the --install-dependencies option:
java -jar dda-serverspec-crate-standalone.jar --install-dependencies --targets targets.edn test.edn
  1. Run the jar with the following options and inspect the output. For testing against localhost:
java -jar dda-serverspec-crate-standalone.jar serverspec.edn

For testing remote server(s) please specify the targets file:

java -jar dda-serverspec-crate-standalone.jar --targets targets.edn serverspec.edn

Additional-info-about-the-configuration

Two configuration files are required by the dda-serverspec-crate:: "serverspec.edn" and "targets.edn" (or similar names). These files specify both WHAT to test resp. WHERE. In detail: the first file defines the configuration for the actual tests performed, while the second configuration file specifies the target nodes/systems, on which the tests will be performed. The following examples will explain these files more in details.

(Remark: The second file "targets.edn" is optional. This means, if none is specified, then a default file is used, which defines that the tests are performed against localhost.)

Targets-config-example

{:existing [{:node-name "test-vm1"
             :node-ip "35.157.19.218"}
            {:node-name "test-vm2"
             :node-ip "18.194.113.138"}]
 :provisioning-user {:login "ubuntu"}}

The keyword :existing has to be assigned a vector, that contains maps with the information about the nodes. The nodes are the target machines that will be tested. The node-name has to be set to be able to identify the target machine and the node-ip has to be set so that the source machine can reach it. The provisioning-user has to be the same for all nodes that will be tested. Furthermore, if the ssh-key of the executing host is authorized on all target nodes, a password for authorization can be omitted. If this is not the case, the provisioning user has to contain a password.

Serverspec-config-example

{:netstat [{:process-name "sshd" :port "11" :running? false}
           {:process-name "sshd" :port "22" :exp-proto "tcp6" :ip "::"}]
 :file [{:path "/root" :user "root"}
        {:path "/etc"}
        {:path "/absent" :exist? false}
        {:path "/etc/resolv.conf" :link-to "../run/resolvconf/resolv.conf"}]
 :netcat [{:host "www.google.com" :port 80}
          {:host "www.google.c" :port 80 :reachable? false}]
 :package [{:name "test" :installed? false}
           {:name "nano"}]}

The serverspec config file determines the tests that are executed. For example the part containing {:path "/root" :user "root"} checks if the folder /root exists and is owned by the root user. There are different types of tests that can be used. More details can be found in the reference below.

Reference

You will find here the reference for

  • target: How targets can be specified
  • Domain-Level-API: The high level API with many built-in conventions.
  • Infra-Level-API: If the domain conventions don't fit your needs, you can use our low-level API (infra) and easily realize your own conventions.

Targets

The schema of the domain layer for the targets is:

(def ExistingNode
  "Represents a target node with ip and its name."
  {:node-name s/Str   ; semantic name (keep the default or use a name that suits you)
   :node-ip s/Str})   ; the ip4 address of the machine to be provisioned

(def ExistingNodes
  "A sequence of ExistingNodes."
  {s/Keyword [ExistingNode]})

(def ProvisioningUser
  "User used for provisioning."
  {:login s/Str                                ; user on the target machine, must have sudo rights
   (s/optional-key :password) secret/Secret})  ; password can be ommited, if a ssh key is authorized

(def Targets
  "Targets to be used during provisioning."
  {:existing [ExistingNode]                                ; one ore more target nodes.
   (s/optional-key :provisioning-user) ProvisioningUser})  ; user can be ommited to execute on localhost with current user

The "targets.edn" file has to match this schema.

Domain-API

The schema for the tests is:

(def ServerTestDomainConfig
  {(s/optional-key :package) [{:name s/Str
                               (s/optional-key :installed?) s/Bool}]
   (s/optional-key :netstat) [{:process-name s/Str             ; works only for sudoer.
                               :port s/Str
                               (s/optional-key :running?) s/Bool
                               (s/optional-key :ip) s/Str
                               (s/optional-key :exp-proto) s/Str}]
   (s/optional-key :file) [{:path s/Str
                            (s/optional-key :exist?) s/Bool
                            (s/optional-key :mod) s/Str
                            (s/optional-key :user) s/Str
                            (s/optional-key :group) s/Str
                            (s/optional-key :link-to) s/Str}]
   (s/optional-key :netcat) [{:host s/Str
                              :port s/Num
                              (s/optional-key :reachable?) s/Bool}]
   (s/optional-key :certificate) [{:file s/Str                ; incl path as e.g. /path/file.crt
                                   :expiration-days s/Num}]   ; min days certificate must be valid
   (s/optional-key :http) [{:url s/Str                        ; url e.g. http://google.com
                            :expiration-days s/Num}]})        ; min days certificate must be valid

The "tests.edn" file has to match this schema. The default value is that the test expects a positive boolean (e.g. :reachable? true) and this value can be omitted.

Infra-API

The infra configuration is a configuration on the infrastructure level of a crate. It contains the complete configuration options that are possible with the crate functions. On infra level we distinguish between collecting facts (done in the settings phase without side effects) and testing (done in test phase intentionally without side effects). Settings can also be used without tests in order to provide informations for conditional installations / configurations.

The schema is:

(def ServerTestConfig {
  (optional-key :netstat-fact) Any,      ; parsed result of "netstat -tulpen". Any is ignored. Fact can only be collected by sudoers / root.
  (optional-key :package-fact) Any})     ; parsed result of "dpkg -l". Any is ignored.
  (optional-key :file-fact)              ; parsed result of "find [path] -prune -printf \"%p'%s'%u'%g'%m'%y'%c'%t'%a\\n\", fact can be collected only if executing user has access.
  {Keyword {:path Str}},
  (optional-key :netcat-fact)            ; parsed result of "nc [host] -w [timeout] && echo $?"
  {Keyword {:port Num,
            :host Str,                   ; may be ip or fqdn
            :timeout Num}},              ; timeout given in seconds
  (optional-key :certificate-file-fact)  ; fact can only be collected is executing user has access.
  {Keyword {:file Str}}                  ; with full path
  (optional-key :http-fact)
  {Keyword {:url Str}}                   ; full url e.g. https://google.com
  (optional-key :package-test)
  {Keyword {:installed? Bool}},
  (optional-key :netstat-test)
  {Keyword {:running? Bool,
            :port Str,
            (optional-key :ip) Str,
            (optional-key :exp-proto) Str}},
  (optional-key :file-test)
  {s/Keyword {:exist? Bool
              (optional-key :mod) Str
              (optional-key :user) Str
              (optional-key :group) Str
              (optional-key :type) Str
              (optional-key :link-to) Str}}
  (optional-key :netcat-test)
  {Keyword {:reachable? Bool}},
  (optional-key :certificate-file-test)
  {Keyword {:expiration-days Num}}
  (optional-key :http-test)
  {Keyword {:expiration-days Num}}})

On the level of the infrastructure we break down the tests into gathering the facts and testing them against the expected value. These results are returned in a map that follows the schema depicted above.

Compatibility

dda-pallet is compatible with the following versions

  • pallet 0.8
  • clojure 1.7
  • (x)ubunutu 16.0

License

Copyright © 2015, 2016, 2017, 2018 meissa GmbH Published under apache2.0 license

Can you improve this documentation?Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close