Category: ansible

Add a simple custom action and action alias to stackstorm

In this post I will demonstrate adding a ping action to stackstorm. Then make that action available from chatops (slack) using an action alias.

The Scenario

On a team of network engineers often certain ip addresses need to be checked if they are accessible. This is done using the ping command. If an engineers would like to give visibility on the status of that ping command, she could make that ping command via her chat application. Then everyone in the same room would be able to see the result.

Create the Ping Action

Lets check what this action does, ssh into your stackstorm instance and run:


[cent@st2 packs]$ ping -c 4 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=1 ttl=59 time=3.15 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=59 time=2.99 ms
64 bytes from 1.1.1.1: icmp_seq=3 ttl=59 time=2.69 ms
64 bytes from 1.1.1.1: icmp_seq=4 ttl=59 time=2.73 ms

--- 1.1.1.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3002ms
rtt min/avg/max/mdev = 2.696/2.894/3.157/0.201 ms

this is what we want to do, but instead of manually typing the command we want stackstorm to do the action.

Let us use the core.local action to run the command:


[cent@st2 packs]$ st2 run core.local -- ping -c 4 1.1.1.1
..
id: 5cdeb8bb52364c6d5cb1d90f
status: succeeded
parameters: 
  cmd: ping -c 4 1.1.1.1
result: 
  failed: false
  return_code: 0
  stderr: ''
  stdout: 'PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
    64 bytes from 1.1.1.1: icmp_seq=1 ttl=59 time=3.17 ms
    64 bytes from 1.1.1.1: icmp_seq=2 ttl=59 time=3.09 ms
    64 bytes from 1.1.1.1: icmp_seq=3 ttl=59 time=2.89 ms
    64 bytes from 1.1.1.1: icmp_seq=4 ttl=59 time=2.75 ms

    --- 1.1.1.1 ping statistics ---
    4 packets transmitted, 4 received, 0% packet loss, time 3003ms
    rtt min/avg/max/mdev = 2.759/2.981/3.171/0.167 ms'
  succeeded: true

So now stackstorm has run the action.

Now create a custom pack folder in /opt/stackstorm/packs and create a folder within that called actions and then create a file called ping.yaml within that. That file should contain:


---
description: Action that executes the Linux ping command on the localhost.
runner_type: "local-shell-cmd"
enabled: true
entry_point: ''
name: ping
parameters:
  ip:
    description: The ip address to ping
    type: string
    required: true
  cmd:
    description: Arbitrary Linux command to be executed on the local host.
    required: true
    type: string
    default: 'ping -c4 {{ip}}'
    immutable: true
  kwarg_op:
    immutable: true
  sudo:
    default: false
    immutable: true
  sudo_password:
    immutable: true

 

We are running a local shell command, I’m not 100% on the other paramters and if they are even needed but the cmd command is and is defaulted to ping -c4 {{ ip}} where we intepolate ip.

Now we reload stackstorm to pickup the action: st2ctl reload

Then we run the action: st2 action run my_pack.ping ip=1.1.1.1

Sorted.

Create the Action Alias

Now we are going to create the alias so that the ping can be called from slack.

In /opt/stackstorm/packs/my_pack/aliases/ping.yaml add:

 


---
name: "ping"
pack: "my_pack"
action_ref: "my_pack.ping"
description: "Execute a local ping."
formats:
  - "ping {{ ip }}"

Now you need to reload stackstorm: sudo sysctl reload.
The action should now be available on slack (if you have set chatops up).

Next thing, is the alias will not show up in help if you have not restarted the chatops service, so let us do that now: sudo systemctl restart chatops

when you do !help your alias will now be there:

st2-ping-custom-alias

So let’s run it (remember you can also @botname to run the command): @mybot ping 8.8.8.8

stackstorm-ping-alias-with-slack

So that is a good demo.

Deploying Stackstorm to a server with Ansible

The information about deploying stackstorm to a server with ansible is in the stackstorm docs.

Importantly the galaxy role can’t really be used like a normal ansible-galaxy role.

You have to clone the repo:


git clone https://github.com/StackStorm/ansible-st2
cd ansible-st2

Then update the inventory, for example in inventory:


st2 ansible_host=10.200.1.76 ansible_user=cent ansible_sudo_pass=pass

Run the playbook:


ansible-playbook -i inventory stackstorm.yml

 

Check your version on the managed host:


st2 --version

Installing Ansible Pack

If you check the stackstorm ansible pack some requirements are required beforehand.

sudo yum install gcc krb5-devel

I then installed python36 and python36-pip.

The pack then installed from the backend.

 

Getting Jenkins to deploy with ansible using SSH Agent Forwarding

Your CI/CD tool needs access to code and server, for linting, testing and deploying.
Setup up access on the various devices in a secure manner can be very time consuming. It is important to make use of available technology to make our lives easier.

Jenkins needs access

You will have created credentials for Jenkins – by creating a SSH key pair for your jenkins user. Ensure that that public key have access to the code on your version control platform (as a deploy key).

Now jenkins will be able to get your code and run various tests on it. The problem now is deployment.

jenkins-credentials

Use Jenkins’s SSH credentials to Deploy

We are using ansible to deploy (from the jenkins box). So now jenkins needs access to wherever you are deploying the code to. You would do an ssh-copy-id to get it there.

But there is another problem, when ansible runs the git module to clone the repo you will get an error that the user does not have access.

Correct, the user on the box you are deploying to does not have access to the code. Now you could add that box as another deploy key but now when scaling out to many boxes you will have a hell of alot of ssh credentials to manage.

The best thing to do is use the jenkins user’s cerentials that log into your target box to get the code. This is done with SSH Agent forwarding.

The first thing we will need is theĀ  jenkins SSH agent plugin.

Then enable the SSH agent for your job:

enable-jenkins-ssh-agent

 

Then install the Jenkins ansible plugin and configure it.

Finally you need to tell ansible to use SSH Agent forwarding, otherwise it just won’t do it:


mkdir /etc/ansible
vi /etc/ansiible/ansible.cfg

Add the following config there:


defaults]
host_key_checking = False

[ssh_connection]
ssh_args = -o ForwardAgent=yes -o ControlMaster=auto -o ControlPersist=60s

Of course, it is better to ensure host_key_checking is done.

Now everything should work.

Source: SSH Agent Forwarding with Ansible