AnsibleでCisco Sparkに投稿 - cisco_spark

#背景
Ansible2.3でサポートされたらしい[cisco_sparkモジュール](https://docs.ansible.com/ansible/cisco_spark_module.html)の動作確認。Cisco Sparkは、無料で使える情報共有ツール（クラウドサービス）。詳しくは[サイトを参照](http://www.cisco.com/c/m/ja_jp/solutions/collaboration/cisco-spark/index.html)。色々取り出して、グループチャットに投げたら嬉しい場合もあるかもしれない。ということで、Cisco系モジュールを使ってルータから取り出した情報を、CiscoSparkに投稿する動作確認をしてみた。

※参考
[AnsibleでCisco IOSの情報収集 - ios_facts](http://qiita.com/kikuta1978/items/f38298bd357f7a315819)
[AnsibleでCisco IOSの情報収集 - ios_commands](http://qiita.com/kikuta1978/items/66993affd83e415f2585)


#準備
※ansible.cfgやinventoryの設定は省略。

##Ansibleのバージョンアップ

```bash
sudo apt-get install software-properties-common
sudo apt-add-repository ppa:ansible/ansible
sudo apt-get update
sudo apt-get install ansible
```

```bash
kikuta@ubuntu1:~/Ansible$ ansible --version
ansible 2.3.1.0
  config file = /home/kikuta/Ansible/ansible.cfg
  configured module search path = Default w/o overrides
  python version = 2.7.6 (default, Oct 26 2016, 20:30:19) [GCC 4.8.4]
```

##Cisco Spark
###アカウント作成とスペースの作成
- こんな感じ。テスト用に自分だけのスペースを利用。
![SS 2017-06-17 4.10.30.png](https://qiita-image-store.s3.amazonaws.com/0/157325/0373578a-e33e-adf5-9568-e41903b399ff.png)

###アクセストークンの取得
- [CiscoSparkのディベロッパーサイト](https://developer.ciscospark.com/)でアカウントをアクティベート
- 自分のアイコンをクリックすると、アクセストークンが得られる
![SS 2017-06-17 4.17.43.png](https://qiita-image-store.s3.amazonaws.com/0/157325/20f2dee9-1f5e-fd56-5ba6-94452097ae56.png)

###スペースのID（RoomID）の検索

スペース名からルームIDを検索 - [Get Room Detail](https://developer.ciscospark.com/endpoint-rooms-roomId-get.html
)
![SS 2017-06-17 4.22.25.png](https://qiita-image-store.s3.amazonaws.com/0/157325/7120e348-d982-97a3-eb6c-bb3d0749412d.png)

###アクセストークンとRoomIDを変数に追加
- inventoryに追加 -> SparkRoomId, KikutaSparkToken

※後で使いやすいように


#例 - ios_factsで適当に取り出してSparkに投稿

##Playbook - ios_fact_spark.yml
```yaml:ios_fact_spark.yml
---
- hosts: ios
  gather_facts: yes 
  connection: local

  tasks:
    - ios_facts:
        gather_subset: all
        provider: "{{ cli }}"
      register: result

    - name: DEBUG
      debug: var=result

    - name: Cisco Spark - Text Message to a Room
      cisco_spark:
        recipient_type: roomId
        recipient_id: "{{ SparkRoomId }}" 
        message_type: text
        personal_token: "{{ KikutaSparkToken }}"
        message: >
           "ホスト名： {{ result['ansible_facts']['ansible_net_hostname'] }} 
            シリアル番号： {{ result['ansible_facts']['ansible_net_serialnum'] }} 
            IOSバージョン：{{ result['ansible_facts']['ansible_net_version'] }}
            確認時刻：{{ ansible_date_time.year }}{{ ansible_date_time.month }}{{ ansible_date_time.day }}{{ ansible_date_time.hour }}{{ ansible_date_time.minute }}{{ ansible_date_time.second }}"

  vars:
    cli:
      host: "{{ inventory_hostname }}"
      authorize: yes
      username: "{{ ansible_ssh_user }}"
      password: "{{ ansible_ssh_pass }}"
      auth_pass: "{{ enable_pass }}"
```

##実行例

```bash
kikuta@ubuntu1:~/Ansible$ ansible-playbook ios_facts_spark.yml

PLAY [ios] **************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************
ok: [10.71.130.57]

TASK [ios_facts] ********************************************************************************************************************
ok: [10.71.130.57]

TASK [DEBUG] ************************************************************************************************************************
ok: [10.71.130.57] => {
    "result": {
        "ansible_facts": {
            "ansible_net_all_ipv4_addresses": [
                "10.71.130.57"
            ], 
            "ansible_net_all_ipv6_addresses": [], 
            "ansible_net_config": "Building configuration...\n\nCurrent configuration : 4580 bytes\n!\n! Last configuration change at 23:32:09 UTC Sun Jun 11 2017\n!\nversion 16.5\nservice config\nservice timestamps debug datetime msec\nservice timestamps log datetime msec\nplatform qfp utilization monitor load 80\nno platform punt-keepalive disable-kernel-core\nplatform console auto\n!\nhostname CSR1KV-1\n!\nboot-start-marker\nboot-end-marker\n!\n!\nenable secret 5 $1$ZLh8$gARnQgM7NKG.4Z1rjb90H0\n!\n!\ntransport-map type persistent webui https-webui\n secure-server\n!\naaa new-model\n!\n!\naaa authorization exec default local \n!\n!\n!\n!\n!\naaa session-id common\n!\n!\n!\n!\naaa session-id common\n!\n!\n!\n!\n!\n!\n!\n!\n!\n\nno ip domain lookup\nip domain name solse.local\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\nsubscriber templating\n! \n! \n! \n! \n!\n!\n!\nmultilink bundle-name authenticated\n!\n!\n!\n!\n!\ncrypto pki trustpoint TP-self-signed-434643758\n enrollment selfsigned\n subject-name cn=IOS-Self-Signed-Certificate-434643758\n revocation-check none\n rsakeypair TP-self-signed-434643758\n!\n!\ncrypto pki certificate chain TP-self-signed-434643758\n certificate self-signed 01\n  3082032E 30820216 A0030201 02020101 300D0609 2A864886 F70D0101 05050030 \n  30312E30 2C060355 04031325 494F532D 53656C66 2D536967 6E65642D 43657274 \n  69666963 6174652D 34333436 34333735 38301E17 0D313730 34323030 39353231 \n  375A170D 32303031 30313030 30303030 5A303031 2E302C06 03550403 1325494F \n  532D5365 6C662D53 69676E65 642D4365 72746966 69636174 652D3433 34363433 \n  37353830 82012230 0D06092A 864886F7 0D010101 05000382 010F0030 82010A02 \n  82010100 A797CC35 413CBA17 B64F0B84 37B0372B 9A03FCEB 40C29AE9 A9E8E2BF \n  698C2B15 8BD9BACD BF424293 05F153DB F083EB83 3DC9C85D 9801376E 8531F336 \n  E2F4AD24 8172C1FC E8E66BA8 D78E1351 74E2B8CE AC722E44 4D1F02D6 9FEDF8D3 \n  4E152A34 7A9216F5 2B32D102 EC3AE393 606F31EF 0923C20F DE68B31E B77218B8 \n  D855DEAD 1F39022E A2551EE3 15709C6A 7F8368E4 7B17A708 7B6F4E48 C018E04B \n  29A9FCB3 D78A9C4E 91AF1DA5 5BC1BC5A DD4BFA60 FE1D844E 9BACDC13 E1F91E12 \n  4C3F5AE4 373C96CA 7A59234E FB982F89 A9C9A7CB 8C87F568 26CED0C4 F156419D \n  90EA2D31 2110F924 721A9987 D4FC092B 06A6A11C 3355C56D 07C77B68 B6DB6925 \n  6F156955 02030100 01A35330 51300F06 03551D13 0101FF04 05300301 01FF301F \n  0603551D 23041830 16801465 E91F3E32 5707931B AFA7BB67 510B0A99 0D81F530 \n  1D060355 1D0E0416 041465E9 1F3E3257 07931BAF A7BB6751 0B0A990D 81F5300D \n  06092A86 4886F70D 01010505 00038201 010015A9 E921CD14 55CE612B D4428131 \n  3677B62F 9DB5D2E8 8332CA08 D3C4396A 5516C70E 5A27A1FE ACF159D8 C1F30128 \n  84C325D1 65D4C289 EDACD513 55BC9058 9B305644 88CC9A99 D2E86D39 8A09A886 \n  4033F0D9 591C722E 2D850841 0316EEF5 22E11AD7 B19C12E0 A7950EE2 B8D30619 \n  4D29B23D 031E5E82 6A04BA59 FEF586BD 60AFA235 9E1C27EA 9DCC447E AF09880C \n  06F80F49 4BD14826 DD1A8BF9 51AFAFA5 5A8F7045 B230CA37 4E468578 24101595 \n  228B5FC1 D236E5D1 603B2C76 EA7F4930 0A76DA8A 971888B2 18A2361A E6654EE0 \n  260411D0 63A56D56 973F7E1D 11F9361C F1997EA2 DED93DC2 5CC6A6C9 EABBFEC9 \n  5BEA603E 6E64922E 13B8A56D 95F4EAA6 21A5\n  \tquit\n!\n!\n!\n!\n!\n!\n!\n!\nlicense udi pid CSR1000V sn 9ZN21QFK61A\nlicense accept end user agreement\nlicense boot level ax\ndiagnostic bootup level minimal\n!\nspanning-tree extend system-id\nnetconf-yang ********-odm actions BGP\nnetconf-yang ********-odm actions OSPF\nnetconf-yang ********-odm actions IPRoute\nnetconf-yang ********-odm actions Diffserv\nnetconf-yang ********-odm actions FlowMonitor\nnetconf-yang ********-odm actions BFDNeighbors\nnetconf-yang ********-odm actions BridgeDomain\nnetconf-yang ********-odm actions VirtualService\nnetconf-yang ********-odm actions EthernetCFMStats\nnetconf-yang ********-odm actions MPLSLDPNeighbors\nnetconf-yang ********-odm actions PlatformSoftware\nnetconf-yang ********-odm actions MPLSStaticBinding\nnetconf-yang ********-odm actions MPLSForwardingTable\nnetconf-yang\n!\n!\nusername ******** privilege 15 password 0 ********\n!\nredundancy\n!\n!\n!\n!\n!\n!\n! \n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n! \n! \n!\n!\ninterface GigabitEthernet1\n ip address 10.71.130.57 255.255.248.0\n negotiation auto\n no mop enabled\n no mop sysid\n!\n\nthreat-visibility\n!\nvirtual-service\n signing level unsigned\n!\n!\nvirtual-service csr_mgmt\n ip shared host-interface GigabitEthernet1\n activate\n!\nip forward-protocol nd\nip http server\nip http authentication local\nip http secure-server\nip route 0.0.0.0 0.0.0.0 10.71.135.254\n!\nip ssh server algorithm encryption aes128-ctr aes192-ctr aes256-ctr\nip ssh client algorithm encryption aes128-ctr aes192-ctr aes256-ctr\n!\n!\n!\n!\n!\n!\n!\ncontrol-plane\n!\n !\n !\n !\n !\n!\n!\n!\n!\nbanner motd ^CHello, YDK^C\n!\nline con 0\n stopbits 1\nline vty 0 4\n transport input all\n!\ntransport type persistent webui input https-webui\n!\nntp server ip ntp-hoge\nnetconf ssh\n!\n!\n!\n!\n!\nend", 
            "ansible_net_filesystems": [
                "bootflash:"
            ], 
            "ansible_net_gather_subset": [
                "hardware", 
                "default", 
                "interfaces", 
                "config"
            ], 
            "ansible_net_hostname": "CSR1KV-1", 
            "ansible_net_image": "bootflash:packages.conf", 
            "ansible_net_interfaces": {
                "GigabitEthernet1": {
                    "bandwidth": 1000000, 
                    "description": null, 
                    "duplex": "Full", 
                    "ipv4": {
                        "address": "10.71.130.57", 
                        "masklen": 21
                    }, 
                    "lineprotocol": "up ", 
                    "macaddress": "0050.56a2.6182", 
                    "mediatype": "RJ45", 
                    "mtu": 1500, 
                    "operstatus": "up", 
                    "type": "CSR vNIC"
                }
            }, 
            "ansible_net_memfree_mb": 1962942, 
            "ansible_net_memtotal_mb": 2301942, 
            "ansible_net_model": null, 
            "ansible_net_neighbors": {
                "null": [
                    {
                        "host": null, 
                        "port": null
                    }
                ]
            }, 
            "ansible_net_serialnum": "9ZN21QFK61A", 
            "ansible_net_version": "16.5.1b"
        }, 
        "changed": false
    }
}

TASK [Cisco Spark - Text Message to a Room] *****************************************************************************************
ok: [10.71.130.57]

PLAY RECAP **************************************************************************************************************************
10.71.130.57               : ok=4    changed=0    unreachable=0    failed=0   

kikuta@ubuntu1:~/Ansible$ 
```

##Cisco Sparkへの投稿を確認
![SS 2017-06-17 4.30.43.png](https://qiita-image-store.s3.amazonaws.com/0/157325/c370c5b1-3525-70e3-75a8-4494accb86a1.png)


#例 - ios_commandsで適当に取り出してSparkに投稿

##Playbook - ios_commands_spark.yml
```yaml:ios_commands_spark.yml
---
- hosts: ios
  gather_facts: yes 
  connection: local

  tasks:
    - name: ios_facts to get returned values
      ios_facts:
        gather_subset:
          - interfaces
        provider: "{{ cli }}"

    - name: run multiple IOS exec commands
      ios_command:
        commands:
          - show arp
          - show ip route
        provider: "{{ cli }}"
        timeout: 30
      register: result

    - name: DEBUG
      debug: var=result

    - name: Cisco Spark - Text Message to a Room
      cisco_spark:
        recipient_type: roomId
        recipient_id: "{{ SparkRoomId }}" 
        message_type: text
        personal_token: "{{ KikutaSparkToken }}"
        message: >
                "ARPエントリ数：{{ result['stdout_lines'][0]|length - 1 }}
                 コマンド出力結果：
                 {{ result['stdout']}}
                 --------------------
                 確認時刻：{{ ansible_date_time.year }}{{ ansible_date_time.month }}{{ ansible_date_time.day }}{{ ansible_date_time.hour }}{{ ansible_date_time.minute }}{{ ansible_date_time.second }}
                 --------------------"

  vars:
    cli:
      host: "{{ inventory_hostname }}"
      authorize: yes
      username: "{{ ansible_ssh_user }}"
      password: "{{ ansible_ssh_pass }}"
      auth_pass: "{{ enable_pass }}"
```

##実行例

```bash
kikuta@ubuntu1:~/Ansible$ ansible-playbook ios_commands_spark.yml 

PLAY [ios] ******************************************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************************************
ok: [10.71.130.57]

TASK [ios_facts to get returned values] *************************************************************************************************************************************
ok: [10.71.130.57]

TASK [run multiple IOS exec commands] ***************************************************************************************************************************************
 [WARNING]: argument timeout has been deprecated and will be removed in a future version

ok: [10.71.130.57]

TASK [DEBUG] ****************************************************************************************************************************************************************
ok: [10.71.130.57] => {
    "result": {
        "changed": false, 
        "stdout": [
            "Protocol  Address          Age (min)  Hardware Addr   Type   Interface\nInternet  10.71.129.10            3   0050.5600.0101  ARPA   GigabitEthernet1\nInternet  10.71.129.111           3   000c.2952.a7c8  ARPA   GigabitEthernet1\nInternet  10.71.129.159           3   0050.5600.0201  ARPA   GigabitEthernet1\nInternet  10.71.130.44            3   000c.2962.b65c  ARPA   GigabitEthernet1\nInternet  10.71.130.56            4   0050.56a2.3c16  ARPA   GigabitEthernet1\nInternet  10.71.130.57            -   0050.56a2.6182  ARPA   GigabitEthernet1\nInternet  10.71.130.58          247   0050.56a2.6a84  ARPA   GigabitEthernet1\nInternet  10.71.132.30            3   0050.5698.77b3  ARPA   GigabitEthernet1\nInternet  10.71.132.31            3   0050.56b0.e957  ARPA   GigabitEthernet1\nInternet  10.71.132.39            3   0050.56b0.b99d  ARPA   GigabitEthernet1\nInternet  10.71.132.49            3   0050.56b0.af2c  ARPA   GigabitEthernet1\nInternet  10.71.132.105         109   5897.bdb9.b6c5  ARPA   GigabitEthernet1\nInternet  10.71.133.16            3   0050.5698.cb54  ARPA   GigabitEthernet1\nInternet  10.71.133.149           3   000c.2915.7b19  ARPA   GigabitEthernet1\nInternet  10.71.133.182           0   0050.56a9.0d86  ARPA   GigabitEthernet1\nInternet  10.71.133.184           0   0050.56a9.36fb  ARPA   GigabitEthernet1\nInternet  10.71.133.223          60   000c.29aa.30be  ARPA   GigabitEthernet1\nInternet  10.71.133.227          60   0050.56a9.501c  ARPA   GigabitEthernet1\nInternet  10.71.134.76            3   000c.297e.b275  ARPA   GigabitEthernet1\nInternet  10.71.134.88           62   0019.309f.f640  ARPA   GigabitEthernet1\nInternet  10.71.134.131           3   0050.56a5.72ac  ARPA   GigabitEthernet1\nInternet  10.71.134.139           3   0050.56a5.6318  ARPA   GigabitEthernet1\nInternet  10.71.134.187           3   0050.5698.e9bb  ARPA   GigabitEthernet1\nInternet  10.71.134.226           3   0050.56a2.ac37  ARPA   GigabitEthernet1\nInternet  10.71.135.58            0   000c.29cc.a3fd  ARPA   GigabitEthernet1\nInternet  10.71.135.254           0   0019.a992.5c40  ARPA   GigabitEthernet1\nInternet  10.71.141.74            0   0022.e440.451f  ARPA   GigabitEthernet1", 
            "Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP\n       D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area \n       N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2\n       E1 - OSPF external type 1, E2 - OSPF external type 2\n       i - IS-IS, su - IS-IS summary, L1 - IS-IS level-1, L2 - IS-IS level-2\n       ia - IS-IS inter area, * - candidate default, U - per-user static route\n       o - ODR, P - periodic downloaded static route, H - NHRP, l - LISP\n       a - application route\n       + - replicated route, % - next hop override, p - overrides from PfR\n\nGateway of last resort is 10.71.135.254 to network 0.0.0.0\n\nS*    0.0.0.0/0 [1/0] via 10.71.135.254\n      10.0.0.0/8 is variably subnetted, 2 subnets, 2 masks\nC        10.71.128.0/21 is directly connected, GigabitEthernet1\nL        10.71.130.57/32 is directly connected, GigabitEthernet1"
        ], 
        "stdout_lines": [
            [
                "Protocol  Address          Age (min)  Hardware Addr   Type   Interface", 
                "Internet  10.71.129.10            3   0050.5600.0101  ARPA   GigabitEthernet1", 
                "Internet  10.71.129.111           3   000c.2952.a7c8  ARPA   GigabitEthernet1", 
                "Internet  10.71.129.159           3   0050.5600.0201  ARPA   GigabitEthernet1", 
                "Internet  10.71.130.44            3   000c.2962.b65c  ARPA   GigabitEthernet1", 
                "Internet  10.71.130.56            4   0050.56a2.3c16  ARPA   GigabitEthernet1", 
                "Internet  10.71.130.57            -   0050.56a2.6182  ARPA   GigabitEthernet1", 
                "Internet  10.71.130.58          247   0050.56a2.6a84  ARPA   GigabitEthernet1", 
                "Internet  10.71.132.30            3   0050.5698.77b3  ARPA   GigabitEthernet1", 
                "Internet  10.71.132.31            3   0050.56b0.e957  ARPA   GigabitEthernet1", 
                "Internet  10.71.132.39            3   0050.56b0.b99d  ARPA   GigabitEthernet1", 
                "Internet  10.71.132.49            3   0050.56b0.af2c  ARPA   GigabitEthernet1", 
                "Internet  10.71.132.105         109   5897.bdb9.b6c5  ARPA   GigabitEthernet1", 
                "Internet  10.71.133.16            3   0050.5698.cb54  ARPA   GigabitEthernet1", 
                "Internet  10.71.133.149           3   000c.2915.7b19  ARPA   GigabitEthernet1", 
                "Internet  10.71.133.182           0   0050.56a9.0d86  ARPA   GigabitEthernet1", 
                "Internet  10.71.133.184           0   0050.56a9.36fb  ARPA   GigabitEthernet1", 
                "Internet  10.71.133.223          60   000c.29aa.30be  ARPA   GigabitEthernet1", 
                "Internet  10.71.133.227          60   0050.56a9.501c  ARPA   GigabitEthernet1", 
                "Internet  10.71.134.76            3   000c.297e.b275  ARPA   GigabitEthernet1", 
                "Internet  10.71.134.88           62   0019.309f.f640  ARPA   GigabitEthernet1", 
                "Internet  10.71.134.131           3   0050.56a5.72ac  ARPA   GigabitEthernet1", 
                "Internet  10.71.134.139           3   0050.56a5.6318  ARPA   GigabitEthernet1", 
                "Internet  10.71.134.187           3   0050.5698.e9bb  ARPA   GigabitEthernet1", 
                "Internet  10.71.134.226           3   0050.56a2.ac37  ARPA   GigabitEthernet1", 
                "Internet  10.71.135.58            0   000c.29cc.a3fd  ARPA   GigabitEthernet1", 
                "Internet  10.71.135.254           0   0019.a992.5c40  ARPA   GigabitEthernet1", 
                "Internet  10.71.141.74            0   0022.e440.451f  ARPA   GigabitEthernet1"
            ], 
            [
                "Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP", 
                "       D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area ", 
                "       N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2", 
                "       E1 - OSPF external type 1, E2 - OSPF external type 2", 
                "       i - IS-IS, su - IS-IS summary, L1 - IS-IS level-1, L2 - IS-IS level-2", 
                "       ia - IS-IS inter area, * - candidate default, U - per-user static route", 
                "       o - ODR, P - periodic downloaded static route, H - NHRP, l - LISP", 
                "       a - application route", 
                "       + - replicated route, % - next hop override, p - overrides from PfR", 
                "", 
                "Gateway of last resort is 10.71.135.254 to network 0.0.0.0", 
                "", 
                "S*    0.0.0.0/0 [1/0] via 10.71.135.254", 
                "      10.0.0.0/8 is variably subnetted, 2 subnets, 2 masks", 
                "C        10.71.128.0/21 is directly connected, GigabitEthernet1", 
                "L        10.71.130.57/32 is directly connected, GigabitEthernet1"
            ]
        ], 
        "warnings": [
            "argument timeout has been deprecated and will be removed in a future version"
        ]
    }
}

TASK [Cisco Spark - Text Message to a Room] *********************************************************************************************************************************
ok: [10.71.130.57]

PLAY RECAP ******************************************************************************************************************************************************************
10.71.130.57               : ok=5    changed=0    unreachable=0    failed=0   

kikuta@ubuntu1:~/Ansible$
```

##Cisco Sparkへの投稿を確認
![SS 2017-06-17 4.58.56.png](https://qiita-image-store.s3.amazonaws.com/0/157325/8106b035-55ec-742c-89e3-02cfa8003d4a.png)

以上です。
簡単に使えるし、色々組み合わせに、使い勝手が良さそうです。