【PostgreSQL】複数レコードを一括更新

まずテーブルを作成します。

create table myschema.product (
  name varchar(10), 
  price integer, 
  stock integer
);

続いてデータを挿入します

insert into product values
  ('Orange', 200, 12),
  ('Melon', 450, 6),
  ('Grape', 320, 8),
  ('Apple', 180, 14),
  ('Peach', 380, 5);

testdb=# select * from product;
name | price | stock
——–+——-+——-
Orange | 200 | 12
Melon | 450 | 6
Grape | 320 | 8
Apple | 180 | 14
Peach | 380 | 5
(5 rows)

testdb=# update product set price=340 where name=’Grape’;
UPDATE 1
testdb=# select * from product;
name | price | stock
——–+——-+——-
Orange | 200 | 12
Melon | 450 | 6
Apple | 180 | 14
Peach | 380 | 5
Grape | 340 | 8

testdb=# update product set price=price-50 where stock < 10; UPDATE 3 testdb=# select * from product; name | price | stock --------+-------+------- Orange | 200 | 12 Apple | 180 | 14 Melon | 400 | 6 Peach | 330 | 5 Grape | 290 | 8 (5 rows) 複数更新する場合も条件式でできるのね。

Basic認証とは

Basic認証はWebの特定の領域にアクセス制限をかける認証方法
Basic認証が設定できる範囲は基本的にディレクトリ単位のみとなる
.htaccessファイルを設置したディレクトリ全体がBasic認証の範囲となる(ルートディレクトリに.htaccessを設置することで全体にベーシック認証をかけている)

### AWS WAFだけのBasic認証の設定
WAF Ruleの作成
– If a request: doesn’t match the statement(NOT)

– Inspect: Header
– Header field name: authorization
– Match type: Exactly matches string
– String to match: Basic xxxxxxx (User:PasswordをBase64エンコードした値を設定)
$ echo -n user:password | base64

Action
– Block
– Enable, 401
– Key: www-authenticate, Value: Basic

Basic認証完了後はブラウザを閉じるまで有効
ベーシック認証は、ユーザーが正しいIDとパスワードで認証に成功した場合、ブラウザを閉じるまでの間は再認証なしで何度でもアクセスすることが可能になります。ブラウザさえ閉じていなければ、仮に、違うWebサイトを閲覧した後でも認証なしで再びアクセスすることが可能です。

ブラウザがログイン情報を記録
一度ベーシック認証で認証に成功してしまえば、ユーザー名とパスワードはブラウザに記憶され、再び入力する手間を省くことができます。ただし、あくまでブラウザに依存する機能なので、ブラウザの種類やバージョン、ネットワークの状態によってはログイン情報が保存されない可能性があります。また、スマホではベーシック認証のログイン情報が保持されないことがほとんどですので、利用する際のブラウザやデバイスには注意が必要です。

なるほど、ブラウザ側の仕様なのね。少し理解した。

macでjmeterを使いたい

Test Plan -> Add -> Thread(Users) -> Thread Group

HTTP Request
HTTP RequestのGet, ip, path, paramなどを設定する

Thread Group
Thread Propertiesの Threads(リクエスト数), Ramp-up period(リクエストの作成期間), Loop Count(リクエスト量)を設定する

Listenerの追加: テスト結果を表示
Summary Reportを追加

なるほど、一通りの機能はわかったが、複数画面はどうやるんだろうか?

ApacheBenchの使い方

ApacheBenchはApache HTTP Serverに同梱されている性能テストツール
単一のURLへのリクエストを生成するツール

$ ab -n 100 -c 10 http://google.com/
nオプション: 生成するリクエスト数
cオプション: 並列実行する数
$ ab -n 100 -c 10 http://google.com/
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking google.com (be patient)…..done

Server Software: gws
Server Hostname: google.com
Server Port: 80

Document Path: /
Document Length: 219 bytes

Concurrency Level: 10
Time taken for tests: 1.533 seconds
Complete requests: 100
Failed requests: 0
Non-2xx responses: 100
Total transferred: 77300 bytes
HTML transferred: 21900 bytes
Requests per second: 65.23 [#/sec] (mean)
Time per request: 153.297 [ms] (mean)
Time per request: 15.330 [ms] (mean, across all concurrent requests)
Transfer rate: 49.24 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 2 3.0 1 13
Processing: 103 134 26.4 128 225
Waiting: 103 132 25.6 126 222
Total: 104 136 26.3 130 226

Percentage of the requests served within a certain time (ms)
50% 130
66% 134
75% 139
80% 142
90% 157
95% 217
98% 226
99% 226
100% 226 (longest request)

なるほど

[AWS] Lambdaのレイヤーサンプル

$ tree
.
└── common
├── layer
│   └── python
│   └── util.py
└── serverless.yml

serverless.yml

service: sample-layer

provider:
  name: aws

layers:
  samplelayer:
    path: layer

util.py

def hello():
	print('Hello, Lambda Layers World!')

serverless.yml

service: sample-function

provider:
  name: aws
  runtime: python3.7
  iamRoleStatements:
  - Effect: "Allow"
    Action:
    - "lambda:InvokeFunction"
    Resource: "*"

functions:
  samplefunction:
    handler: handler.handle_request
    layers:
      - {上記のLayerをsls deployした時に表示されるarn}

handler.py

import util

def handler_request(event, context):
	util.hello()

Layerはデプロイされる度にバージョンが上がる

LayersのARNを確認
$ aws lambda list-layer-versions –layer-name sample-layer –query “LayerVersions[*].LayerVersionArn”
$ aws lambda update-function-configuration –function-name testFunction3 –layers “LayersのARN”

なるほど、なんとなく仕組みと概念は理解した

[AWS] Lambdaのレイヤーとは?

Lambdaレイヤーは追加のコード、データを含むことができる.zipアーカイブ
レイヤーには、ライブラリ、カスタムランタイム、データまたは設定ファイルを含めることができる
レイヤーを使用して共有のコードとの責任の分離を促進することで、ビジネスロジックの記述を迅速に繰り返すことができる
※lambdaでサードパーティライブラリを使うにはLqyerを使う必要がある

標準ライブラリで使える場合とそうでない時がある

from typing import Tuple
import base64
from datetime import datetime, timedelta
import hashlib
import hmac
import json
import os
import random
import re
import string
import sys
import time
from typing import Any, Callable, Dict, List, Tuple
import logging

import jaconv
import openai

関数の上にLqyersがattachされる
1つのLambda関数にattachできるレイヤーは最大5つまで
=> 2つ以上のライブラリを合体させたLqyerを作成
=> 圧縮されたzipファイルのサイズが50MBを超えないこと、展開後のファイルサイズが250MBを超えないこと

### Lambda Layerの作成手順
1. 開発環境を用意
2. 開発環境のPythonバージョンをLambdaと揃える
3. Lambda Layer用のディレクトリを作成
4. 必要なライブラリやモジュールをインストール
5. ディレクトリをZIPファイルに圧縮
6. LambdaコンソールからLambda Layerを作成

– 対象ディレクトリをZIPファイルに圧縮してダウンロード
– LambdaコンソールからLambda Layerを作成

Compatible architecturesに x86_64にチェックを入れる

Lambda LayerをLambda関数に追加する

Layersから呼び出すようにコードを修正する

import json
import logging
 
import config_rules_layer
 
 
logger = logging.getLogger()
logger.setLevel(logging.INFO)
 
def check_ipv4Range_cidrs(inbound_permissions):
    for permission in inbound_permissions:
        logger.info(f'Permission: {permission}')
        if not permission['userIdGroupPairs']:
            for ipv4Range in permission['ipv4Ranges']:
                logger.info(f'ipv4Range: {ipv4Range}')
                if ipv4Range['cidrIp'] == '0.0.0.0/0':
                    logger.warning('Inbound rule includes risks for accessing from unspecified hosts.')
                    return ['NON_COMPLIANT', 'Inbound rule includes risks for accessing from unspecified hosts.']
            return ['COMPLIANT', 'No Problem.']
        else:
            return ['COMPLIANT', 'No Problem.']
 
def evaluate_change_notification_compliance(configuration_item, rule_parameters):
    try:
        config_rules_layer.check_defined(configuration_item, 'configuration_item')
        config_rules_layer.check_defined(configuration_item['configuration'], 'configuration_item[\'configuration\']')
        config_rules_layer.check_defined(configuration_item['configuration']['ipPermissions'], 'ipPermissions')
        inboundPermissions = configuration_item['configuration']['ipPermissions']
        logger.info(f'InboundPermissions: {inboundPermissions}')
        if rule_parameters:
            config_rules_layer.check_defined(rule_parameters, 'rule_parameters')
         
        if configuration_item['resourceType'] != 'AWS::EC2::SecurityGroup':
            logger.info('Resource type is not AWS::EC2:SecurityGroup. This is ', configuration_item['resourceType'], '.')
            return ['NOT_APPLICABLE', 'Resource type is not AWS::EC2:SecurityGroup.']
        
        if inboundPermissions == []:
            return ['COMPLIANT','Inbound rule does not have any permissions.']
        else:
            logger.info('check_ipv4Range_cidrs')
            return check_ipv4Range_cidrs(inboundPermissions)
 
    except KeyError as error:
        logger.error(f'KeyError: {error} is not defined.')
        return ['NOT_APPLICABLE', 'Cannot Evaluation because object is none.']
 
def lambda_handler(event, context):
    global AWS_CONFIG_CLIENT
    AWS_CONFIG_CLIENT = config_rules_layer.get_client('config', event)
 
    invoking_event = json.loads(event['invokingEvent'])
    logger.info(f'invoking_event: {invoking_event}')
    rule_parameters = {}
    if 'ruleParameters' in event:
        rule_parameters = json.loads(event['ruleParameters'])
 
    configuration_item = config_rules_layer.get_configuration_item(invoking_event)
    logger.info(f'configuration_item: {configuration_item}')
    compliance_type = 'NOT_APPLICABLE'
    annotation = 'NOT_APPLICABLE.'
 
    if config_rules_layer.is_applicable(configuration_item, event):
        compliance_type, annotation = evaluate_change_notification_compliance(
            configuration_item, rule_parameters
        )
 
    response = AWS_CONFIG_CLIENT.put_evaluations(
        Evaluations=[
            {
                'ComplianceResourceType': invoking_event['configurationItem']['resourceType'],
                'ComplianceResourceId': invoking_event['configurationItem']['resourceId'],
                'ComplianceType': compliance_type,
                'Annotation': annotation,
                'OrderingTimestamp': invoking_event['configurationItem']['configurationItemCaptureTime']
            },
        ],
        ResultToken=event['resultToken']
    )