shinobe179の日記

@shinobe179 の技術メモ・やらかし録

【AWS】AWS SAM(Serverless Application Model)が手軽にサーバーレス環境作れて便利で感動したって話

はじめに

 サーバーレスアプリケーションを作りたいときのとっかかりとして、 AWS SAM が非常に便利だったのでメモしておきます。ダラダラしてたら2020年はじめての記事になってしまいました。

AWS SAMとは

 公式の解釈は公式を見てもらうとして、触った印象としては Lambda と API Gateway (の CloudFormation テンプレート) のコードをまとめて管理するためのフレームワーク という感じです。「sam」という CLI ツールを通して、テストやデプロイが可能です。Lambda で動かすプログラムだけでなく、エンドポイントである API Gateway もセットで管理できる仕組みである、というところがミソではないかと。

aws.amazon.com

 ていねいに解説できるほど理解していないので、さわりだけ。

インストール

 私は pyenv 環境なので、 --user オプションはつけません。

pip install aws-sam-cli

ひな形の作成

 sam init コマンドを実行すると、ウィザード形式でひな形を出力してくれます。

$ sam init
Which template source would you like to use?
        1 - AWS Quick Start Templates
        2 - Custom Template Location
Choice: 1

Which runtime would you like to use?
        1 - nodejs12.x
        2 - python3.8
        3 - ruby2.7
        4 - go1.x
        5 - java11
        6 - dotnetcore2.1
        7 - nodejs10.x
        8 - python3.7
        9 - python3.6
        10 - python2.7
        11 - ruby2.5
        12 - java8
        13 - dotnetcore2.0
        14 - dotnetcore1.0
Runtime: 2

Project name [sam-app]:

Cloning app templates from https://github.com/awslabs/aws-sam-cli-app-templates.git

AWS quick start application templates:
        1 - Hello World Example
        2 - EventBridge Hello World
        3 - EventBridge App from scratch (100+ Event Schemas)
Template selection: 1

-----------------------
Generating application:
-----------------------
Name: sam-app
Runtime: python3.8
Dependency Manager: pip
Application Template: hello-world
Output Directory: .

Next steps can be found in the README file at ./sam-app/README.md

 ディレクトリ構成は tree の出力が文字化けして萎えたので割愛しますが、アプリ作るにあたってキモは以下の2つだと思います。

Lambda コードのアップロードと CloudFormation テンプレートの作成

 Lambdaのコードは、事前に作成しておいた S3 バケットへアップロードします。 sam package コマンドでバケット名を指定してください。あわせて、 template.yaml から CloudFormation テンプレートを作成します。コードが格納されたバケットの ARN などを自動で置き換えてくれます。

$ sam package --template template.yaml --output-template-name packaged.yaml --s3-bucket test-bucket

デプロイ

 sam deploy コマンドでデプロイします。 正常に作成できれば、 output で API Gateway のエンドポイント URL が表示されるはずです。

$ sam deploy --template-file path/to/template --stack-name test-stack --capabilities CAPABILITY_IAM

Makefile 作っておくと更にお手軽

 Lambda のコードを変更するたびに sam package して sam deploy するのが面倒なので、 Makefile を作って make 一発でどっちもやってくれるようにしてます。本来ならローカルでテストすりゃいいんですけども。

おわり

 AWSCLI がインストール済みなら、マネジメントコンソールからポチポチやるよりも SAM を使ったほうが楽だと思います。楽 = Lambda や API Gateway のことよく分かってなくてもとりあえず動かせるって意味を多分に含んでいるんですが、サーバーレス環境の雰囲気だけでもつかんでおけると、各プロダクトの理解もしやすいんじゃないかと思います。

【ネットワーク】 netdiscover でサブネット内のノードを把握する

はじめに

我が家の インターネット はマンション標準装備のものなんですが、ルーターの管理画面を見られないので、 Wi-Fi にどんな機器が繋がっているのかが分かりません。そこで、 netdiscover を使って同サブネット上に存在するホストを確認してみます。

使い方

インストール

$ sudo apt update
$ sudo apt install netdiscover

実行

$ sudo netdiscover -i wlp3s0 -r 192.168.0.0/16

実際の実行結果は以下のような感じ。

$ sudo netdiscover -i wlp3s0 -r 192.168.0.0/16 
 Currently scanning: Finished!   |   Screen View: Unique Hosts                                                               
                                                                                                                             
 9 Captured ARP Req/Rep packets, from 8 hosts.   Total size: 502                                                             
 _____________________________________________________________________________
   IP            At MAC Address     Count     Len  MAC Vendor / Hostname      
 -----------------------------------------------------------------------------
 192.168.10.231  00:60:b9:XX:XX:XX      1      60  NEC Platforms, Ltd                                                        
 192.168.10.20   24:f0:94:XX:XX:XX      1      42  Unknown vendor                                                            
 192.168.10.27   cc:9e:a2:XX:XX:XX      1      42  Unknown vendor                                                            
 192.168.10.35   cc:f7:35:XX:XX:XX      1      42  Unknown vendor                                                            
 192.168.10.24   c0:e4:34:XX:XX:XX      1     108  Unknown vendor                                                            
 192.168.10.33   4c:56:9d:XX:XX:XX      1      42  Unknown vendor                                                            
 192.168.10.26   bc:83:85:XX:XX:XX      1      42  Unknown vendor                                                            
 192.168.10.234  28:3b:82:XX:XX:XX      2     124  Unknown vendor                                                            

MAC アドレスのベンダーコード

一応 NEC だけは表示してくれましたが、それ以外は Unknown になってしまいました。

以下の記事を参考に、ベンダーコードをベンダー名に変換するコマンド「m2v」を作ってあるので、それで確認してみます。

pslabo.hatenablog.com

リクエスト間を1秒以上開ける必要があるため、元のコードに「sleep 1」を加えています。

#!/bin/sh

# m2v translates MAC address to vendor name.
# cf. https://pslabo.hatenablog.com/entry/2016/03/18/「MACアドレスからベンダーを検索して表示するコマ

if [ $# = 0 ]; then
  echo "[!] Give me args.\nm2v translates MAC address to vendor name.\nusage: m2v mac-address ..."
  exit 1
fi

while [ $# -gt 0 ]; do
  echo -n "$1="
  curl "http://api.macvendors.com/$1"
  echo ""
  shift
  sleep 1
done
$ m2v 00:60:b9:XX:XX:XX 24:f0:94:XX:XX:XX cc:9e:a2:XX:XX:XX cc:f7:35:XX:XX:XX c0:e4:34:XX:XX:XX 4c:56:9d:XX:XX:XX bc:83:85:XX:XX:XX 28:3b:82:XX:XX:XX
00:60:b9:XX:XX:XX=NEC Platforms, Ltd
24:f0:94:XX:XX:XX=Apple, Inc.
cc:9e:a2:XX:XX:XX=Amazon Technologies Inc.
cc:f7:35:XX:XX:XX=Amazon Technologies Inc.
c0:e4:34:XX:XX:XX=AzureWave Technology Inc.
4c:56:9d:XX:XX:XX=Apple, Inc.
bc:83:85:XX:XX:XX=Microsoft Corporation
28:3b:82:XX:XX:XX=D-Link International

AzureWave って何…?と思いましたが、おそらく最近我が家にやって来た Roomba であると思われます。

github.com

ネットワーク機器のインターフェイス名をいい感じにソートする

はじめに

ネットワーク機器のインターフェイス名って、だいたい以下のような感じです。

>>> interfaces = ['GigabitEthernet1/0/' + str(i) for i in range(1, 21)]
>>> for interface in interfaces:
...     print(interface)
... 
GigabitEthernet1/0/1
GigabitEthernet1/0/2
GigabitEthernet1/0/3
GigabitEthernet1/0/4
GigabitEthernet1/0/5
GigabitEthernet1/0/6
GigabitEthernet1/0/7
GigabitEthernet1/0/8
GigabitEthernet1/0/9
GigabitEthernet1/0/10
GigabitEthernet1/0/11
GigabitEthernet1/0/12
GigabitEthernet1/0/13
GigabitEthernet1/0/14
GigabitEthernet1/0/15
GigabitEthernet1/0/16
GigabitEthernet1/0/17
GigabitEthernet1/0/18
GigabitEthernet1/0/19
GigabitEthernet1/0/20
>>> 

単純にソートすると、インターフェイス番号が文字列として扱われてしまうために、きれいに並んでくれません。

>>> for interface in sorted(interfaces):
...     print(interface)
... 
GigabitEthernet1/0/1
GigabitEthernet1/0/10
GigabitEthernet1/0/11
GigabitEthernet1/0/12
GigabitEthernet1/0/13
GigabitEthernet1/0/14
GigabitEthernet1/0/15
GigabitEthernet1/0/16
GigabitEthernet1/0/17
GigabitEthernet1/0/18
GigabitEthernet1/0/19
GigabitEthernet1/0/2
GigabitEthernet1/0/20
GigabitEthernet1/0/3
GigabitEthernet1/0/4
GigabitEthernet1/0/5
GigabitEthernet1/0/6
GigabitEthernet1/0/7
GigabitEthernet1/0/8
GigabitEthernet1/0/9
>>> 

>>> 

sorted の key として関数を指定する

sorted() には key という引数があります。この key に関数が指定されていると、各要素をその関数に入れた戻り値を基準としてソートしてくれます。lambda 式とかを入れる例をよく見ますね。

sorted()key として使うことで、ネットワーク機器のインターフェイス名をいい感じにソートしてくれる関数を書きました。

gist.github.com

こんな感じです。

>>> import sort_by_interface_and_number as sbian
>>> for s in sorted(interfaces, key=sbian.sort_by_interface_and_number):
...     print(s)
... 
GigabitEhternet1/0/1
GigabitEhternet1/0/2
GigabitEhternet1/0/3
GigabitEhternet1/0/4
GigabitEhternet1/0/5
GigabitEhternet1/0/6
GigabitEhternet1/0/7
GigabitEhternet1/0/8
GigabitEhternet1/0/9
GigabitEhternet1/0/10
GigabitEhternet1/0/11
GigabitEhternet1/0/12
GigabitEhternet1/0/13
GigabitEhternet1/0/14
GigabitEhternet1/0/15
GigabitEhternet1/0/16
GigabitEhternet1/0/17
GigabitEhternet1/0/18
GigabitEhternet1/0/19
GigabitEhternet1/0/20
>>> 

仕組み

戻り値のタプルには、引数として受け取ったインターフェイス名のインターフェイス種別とインターフェイス番号がそれぞれ要素として入っています。特に後者は、スラッシュやハイフンなどの記号で分割された番号の位置関係を配列のインデックスで表現し直し、また各番号を(文字列ではなく)数値として格納しています。このタプルをソートの基準になることで、前述のような「いい感じ」のソートができます。

>>> for interface in interfaces:
...     sbian.sort_by_interface_and_number(interface)
... 
('GigabitEhternet', [1, 0, 1])
('GigabitEhternet', [1, 0, 2])
('GigabitEhternet', [1, 0, 3])
('GigabitEhternet', [1, 0, 4])
('GigabitEhternet', [1, 0, 5])
('GigabitEhternet', [1, 0, 6])
('GigabitEhternet', [1, 0, 7])
('GigabitEhternet', [1, 0, 8])
('GigabitEhternet', [1, 0, 9])
('GigabitEhternet', [1, 0, 10])
('GigabitEhternet', [1, 0, 11])
('GigabitEhternet', [1, 0, 12])
('GigabitEhternet', [1, 0, 13])
('GigabitEhternet', [1, 0, 14])
('GigabitEhternet', [1, 0, 15])
('GigabitEhternet', [1, 0, 16])
('GigabitEhternet', [1, 0, 17])
('GigabitEhternet', [1, 0, 18])
('GigabitEhternet', [1, 0, 19])
('GigabitEhternet', [1, 0, 20])
>>> 

必要なくない?

「整形前の時点で大体揃ってる(特に show int status の出力をベースにする時など)から必要ないのでは?」という疑問、もっともです。私の場合、監視サーバーの API を叩いて監視対象になっているネットワーク機器のインターフェイス情報を取得する際に、期待した順番で値が返ってこなかったので、その必要に迫られました。 ifIndex でお茶を濁すというのもなくはないのですが、 Port-Channel や SVI などは作った順で ifindex が割り当てられたりするのが難点です。

【Powershell】Ubuntu 16.04 LTS に Powershell をインストールして Hello World! するまで

はじめに

最近の Windows に標準装備されている Powershell 。覚えたら便利かなと思って、以下のドキュメントを参考に、常用している Ubuntu 16.04 LTS にインストールしました。

docs.microsoft.com

手順

インストール

$ wget -q https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb
$ sudo dpkg -i packages-microsoft-prod.deb
$ sudo apt update
$ sudo apt install -y powershell

Hello World!

pwsh コマンドを実行すると、Powershellインタラクティブシェルが起動します。

$ pwsh
PowerShell 6.2.3
Copyright (c) Microsoft Corporation. All rights reserved.

https://aka.ms/pscore6-docs
Type 'help' to get help.

PS /home/shino/work>

バージョン確認と Hello World! 。

PS /home/shino/work> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      6.2.3
PSEdition                      Core
GitCommitId                    6.2.3
OS                             Linux 4.15.0-72-generic #81~16.04.1-Ubuntu SMP Tue Nov 26 16:34:21 UTC 2019
Platform                       Unix
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

PS /home/shino/work> Write-Host "Hello World!"
Hello World!
PS /home/shino/work>

Linux のコマンドも動くみたいなので、 Linux のコマンドの結果を Powershell に渡すこともできます。

PS /home/shino/work> dmesg | Select-String 'OOM'

[ 2685.911673] OOM killer disabled.
[ 2687.546935] OOM killer enabled.
[ 6856.784239] OOM killer disabled.
[ 6858.378186] OOM killer enabled.
[31045.822107] OOM killer disabled.
[31047.408316] OOM killer enabled.
[41212.257565] OOM killer disabled.
[41213.892290] OOM killer enabled.
[48680.466604] OOM killer disabled.
[48682.096033] OOM killer enabled.
[61149.446007] OOM killer disabled.
[61151.081932] OOM killer enabled.
[70234.583515] OOM killer disabled.
[70236.180446] OOM killer enabled.
[83194.455948] OOM killer disabled.
[83197.967967] OOM killer enabled.
[83400.427023] OOM killer disabled.
[83402.056863] OOM killer enabled.
[84164.491392] OOM killer disabled.
[84166.399293] OOM killer enabled.
[89878.877084] OOM killer disabled.
[89881.111064] OOM killer enabled.
[91969.202935] OOM killer disabled.
[91970.879046] OOM killer enabled.

PS /home/shino/work> 

【Palo Alto】 running と candidate の差分を比較する

はじめに

タイトルの通りです。 Junos の show | compare です。

コマンド

> show config diff

私個人としては、コンフィグレーションモード(#)で先頭に run をつけて実行することのほうが多いです。

参考

knowledgebase.paloaltonetworks.com

【Palo Alto】 show コマンドのページャを無効にする

はじめに

タイトルのとおりです。 Cisco で言うところの ter len 0 ですね。

コマンド

> set cli pager off

参考

knowledgebase.paloaltonetworks.com

【Zabbix】pyzabbix と py-zabbix の違い

はじめに

はじめて使った Zabbix APIPython ラッパーは pyzabbix でした。

github.com

記事も書いてます。

befs-anne.hatenablog.com

しかし、最近はご縁があって(?) py-zabbix というまた別のラッパーを使っています。

github.com

ざっくり、それぞれの使い方をメモしておきます。

インストール

実際のところよく分からないけど、ひとつの環境内で pyzabbix と py-zabbix は同居できないっぽい。

pyzabbix

$ pip install pyzabbix

py-zabbix

$ pip install py-zabbix

インスタンスの作成、ログイン、値の取得

py-zabbix のほうが、インスタンスの作成とログインが同時にできて楽な印象です。

pyzabbix

from pyzabbix import ZabbixAPI

zapi = ZabbixAPI('https://zabbix.example.com')
zapi.login("Admin", "zabbix")
zapi.host.get(search={"name: "prod"}, output=["name", "available"])

py-zabbix

from zabbix.api import ZabbixAPI

zapi = ZabbixAPI('https://zabbix.example.com', user='Admin', password='zabbix')
zapi.do_request('host.get', {'search: {'name': 'prod'}, 'output': ['name']})