ほわいとぼーど

ぷろぐらまのメモ帳

雑にAWSリソースにboto3でタグつけてみたのだが

既存のAWSリソースに管理のためにタグ付け直すことになり
それ用のスクリプトを適当に書いたのだが、
なんでリソース毎にAPIが全然違うのか、という気分になったのでメモる。
ちなみにboto3です。

EC2

read ec2 tag

client = boto3.client('ec2', "ap-northeast-1")
resp = client.describe_instances()
for resv in resp['Reservations']:
    for inst in resv['Instances']
        print(inst['Tags'])

write ec2 tag

client = boto3.client('ec2', "ap-northeast-1")
resp = client.create_tags(
    Resources=[ec2id],
    Tags=[
        { 'Key': 'Env', 'Value': 'production' }
    ]
)

取得はInstanceと一緒に出来るので比較的楽。
むしろReservationsって何って感じだが今回は割愛。
付与は専用だがこれも比較的素直

RDS, ElastiCache

read rds tag

client = boto3.client('rds', "ap-northeast-1")
resp = client.describe_db_instances()
for rds in resp['DBInstances']:
    resp2 = client.list_tags_for_resource(
        ResourceName="arn:aws:rds:ap-northeast-1:accountid:db:" + rds['DBInstanceIdentifier']
    )
    print(resp2['TagList'])

write rds tag

client = boto3.client('rds', "ap-northeast-1")
resp = client.add_tags_to_resource(
    ResourceName="arn:aws:rds:ap-northeast-1:accountid:db:" + dbidentifier,
    Tags=[
        { 'Key': 'Env', 'Value': 'production' }
    ]
)

Tag操作は取得も別メソッド。かつ、リソースの指定方法がARN。

ELB

read elb tag

client = boto3.client('elb', "ap-northeast-1")
resp = client.describe_load_balancers()
for elb in resp['LoadBalancerDescriptions']
    resp2 = client.describe_tags(
        LoadBalancerNames=[elb['LoadBalancerName']]
    )
    for tagdesc in resp2['TagDescriptions']:
        if tagdesc['LoadBalancerName'] == elb['LoadBalancerName']:
            print(tagdesc['Tags'])

write elb tag

client = boto3.client('elb', "ap-northeast-1")
resp = client.add_tags(
    LoadBalancerNames=[elb_name],
    Tags=[
        { 'Key': 'Env', 'Value': 'production' }
    ]
)

取得する方はタグも複数形で帰ってくる。
ではと、複数ELBを指定して一気にとって後で突き合わせればと思ったのだが、
一度に指定できる数が20までと怒られたので結局1個ずつ処理した。
Documentにも上限書いてないのだが・・・
Listタイプのメソッドは結果がページングになっていることはあるが、
入力も分割必要なのは結構ダルい。

付与する方はほぼEC2と一緒。

Kinesis

read kinesis tag

client = boto3.client('kinesis', "ap-northeast-1")
resp = client.list_streams()
for stream_name in resp['StreamNames']:
    resp2 = client.list_tags_for_stream(StreamName=stream_name)
    print(resp2['Tags'])

write kinesis tag

client = boto3.client('kinesis', "ap-northeast-1")
resp = client.add_tags_to_stream(
    StreamName=stream_name,
    Tags={ 'Env': 'production' }
)

一見、RDSに近い(ARNではないが)ように見えるが、
付与する際のTagsの形状が異なることがお分かりになるだろうか。
あと、付与時に複数に連続処理していると、
必ず10個連続実行の後にRateLimitExceptionになったのでtime.sleep挟むようにした。
他のAPIでは待たされることはあってもエラーとなることは無かったので何でコレだけ・・・

Redshift

read redshift tag

client = boto3.client('redshift', "ap-northeast-1")
resp = client.describe_clusters()
for cluster in resp['Clusters']:
    print(cluster['Tags'])

write redshift tag

client = boto3.client('redshift', "ap-northeast-1")
resp = client.create_tags(
    ResourceName="arn:aws:redshift:ap-northeast-1:accountid:cluster:" + cluster_name,
    Tags=[
        { 'Key': 'Env', 'Value': 'production' }
    ]
)

取得は一緒にとれる。付与はARNタイプ

S3

read s3 tag

client = boto3.client('s3', "ap-northeast-1")
resp = client.list_buckets()
for bucket in resp['Buckets']:
    tags = []
    try:
        resp = client.get_bucket_tagging(Bucket=bucket['Name'])
        tags = resp['TagSet']
    except:
        pass
    print(tags)

write s3 tag

client = boto3.client('s3', "ap-northeast-1")
resp = client.put_bucket_tagging(
    Bucket=bucket_name,
    Tagging={
        'TagSet': [
            { 'Key': 'Env', 'Value': 'production' }
        ]
    }
)

意味不明ぽいがTagにアクセスして存在しなかった場合Exceptionになるので
仕方なしにこの形になった・・・
boto3Document一通り眺めたけどすぐには他に思いつかなかず。
ちなみに他のプロパティも同様の挙動をしました。

付与する方も少し階層が他と異なる。

感想

もちろん、処理方法は1種類しかないわけじゃないので違う書き方もできるし、
見落としてる部分もあるかもしれない。
とりあえず各リソースの一覧+タグを拾ってきて、それを更新するのを雑に書いてみた結果です。
ただboto3になったのここ1年くらいだったと思うので思いのほかバラついてるなぁと思った次第。