Rubyと筋肉とギターとわたし

筋トレが仕事です

【aws】vpcネットワークを作っていくメモ

VPCネットワーク

デフォルトVPC

設定名 設定内容 設定の割当最小単位
VPC デフォルトVPC全体のネットワークアドレス。範囲 172.31.0.0/16 リージョン
サブネット 各AZに1つずつ設置。 [/20]のネットワークアドレスが割り当てられる。 AZ
ルートテーブル VPCネットワークアドレス範囲内の通信はVPC内部へルーティング。それ以外はインターネットに向けたルーティング。 サブネット
インターネットゲートウェイ インターネットへの接続用ゲートウェイが作成され、ルートテーブルに割り当てられている。 VPC
ネットワークACL インバウンド・アウトバウンドともに全ての通信を許可 サブネット
セキュリティグループ インバウンドは全ての通信を拒否、アウトバウンドは全ての通信を許可 インスタンス
  • VPCネットワークアドレスは一度設定すると後から変更できないので注意

カスタムVPC

VPC → VPCを作成で新規に作成する。

  • テナンシーを専用にすると利用料が割高に
  • 新規作成時、自動でルートテーブル・ネットワークACL・セキュリティグループが作成される
  • EC2インスタンスでパブリックDNSを使用する場合は、DNSホスト名を有効化する

aws cli経由で作成

$ aws ec2 create-vpc --cidr-block 10.0.0.0/16

# Nameをつけたい場合 *******はVPC ID
$ aws ec2 create-tags --resources vpc-*********** --tags Key=Name,Value=awscli

# hostname 有効化
aws ec2 modify-vpc-attribute --vpc-id vpc-********* --enable-dns-hostnames

サブネット

大きなネットワークを複数の小さなネットワークに分割して管理する際の管理単位となるネットワークのこと。

VPC -> サブネット -> サブネット作成 で新規に作成する。

  • ELBを作成する予定があるサブネットは余裕をもって/24以上のネットワーク範囲で作成すること

aws cli経由で作成

$ aws ec2 create-subnet --vpc-id vpc-*********** --availability-zone ap-northeast-1a --cidr-block 10.0.0.0/24

# tag Name作成(resource idは上記実行時に返ってくるsubnet-***********)
$ aws ec2 create-tags --resources subnet-************ --tags Key=Name,Value=awscli

ルートテーブル

サブネット単位で設定することが出来る、サブネット内で稼働するEC2インスタンスのネットワークルーティングを制御する。

VPCネットワークを作成すると、自動的にルートテーブルも作成される。

VPC -> ルートテーブル -> ルートテーブルの作成で新規に作成する。

aws cli経由で作成

$ aws ec2 create-route-table --vpc-id vpc-****************

# tag name
$ aws ec2 create-tags --resources rtb-************* --tags Key=Name,Value=awscli

作成したサブネットとルートテーブルの関連付け

ルートテーブル -> 作成したルートテーブルを選択 -> サブネットの関連付け -> 編集 -> サブネットにチェックでおk

作成したサブネットはVPC内の1つのルートテーブルに関連付ける必要がある。

  • メインルートテーブルに自動的に関連付けされたサブネットはそのままにせず、明示的にルートテーブルと関連付けるようにする。
  • メインルートテーブルを他のルートテーブルに変更した場合、明示的に関連付けていないサブネットは新たに設定したメインルートテーブルに関連付けられてしまい、それまで出来ていた通信ができなくなったり不要な通信が出来るようになったりする等の問題が発生するため。
  • メインルートテーブルはできるだけ必要最低限のルーティング設定にしておく、VPCの内部通信のみ可能な設定から変更しないようにする

aws cli経由で作成

$ aws ec2 associate-route-table --route-table-id rtb-***************** --subnet-id subnet-******************

インターネットゲートウェイ

VPC内で稼働するEC2インスタンスがインターネットを通じて外部と通信する際に必要。EC2以外のリソースも同様で通信する際に必要。VPCごとに1つだけ紐付けが可能。

ルートテーブルのターゲットとして使用する。

VPC -> インターネットゲートウェイ -> インターネットゲートウェイの作成で新規に作成する。

VPCと関連付ける

アクション -> VPCにアタッチで作成したVPCと関連付けられる。

aws cli経由で作成

$ aws ec2 create-internet-gateway

# tag name(igw-******は上記実行時に取得)
$ aws ec2 create-tags --resources igw-************ --tags Key=Name,Value=awscli-gateway

# VPCへアタッチ
$ aws ec2 attach-internet-gateway --internet-gateway-id igw-*********** --vpc-id vpc-**********

インターネットゲートウェイをルーティング先に指定する

  1. VPC -> ルートテーブル
  2. 作成したルートテーブル選択
  3. 編集
  4. ルートを追加
  5. 送信先 0.0.0.0/0にし、ターゲットをインターネットゲートウェイにし作成した igw idを選択
  6. 変更を保存

aws cli経由で作成

# igw-*******/rtb-*********は先程作成したもの
$ aws ec2 create-route --route-table-id rtb-*************** --destination-cidr-block 0.0.0.0/0 --gateway-id igw-*****************
````

【CSS】tips inputにフォーカスしたときborderの色を変える

どうもてぃ。

CSS力向上を願ってtips記事を書いていきたいと思います。

TL;DR

input:focus-visible {
  outline: 1px solid #ddd;
}

// もしくは
input:focus {
  outline: 1px solid #ddd;
}

inputを装飾している場合…

focus時にoutlineで強調すると、inputにborder-radiusを使っていた場合outlineがradius化してくれず若干違和感を感じる挙動になります。

そんなときは outline: none;にしてbox-shadowで装飾しましょう。

See the Pen by motty (@motty93) on CodePen.

以上。

【vim】vim-prettierがPrettier: failed to parse bufferで動かないときに確認すること

f:id:rdwbocungelt5:20200320131618p:plain

どうもてぃ。

vim + JavaScript/TypeScriptで悩まされる日々が続いておりました。

が、とうとう決着をつけることが出来て感謝カンゲキ雨嵐です(何に?)

何がおきていたか

当方、vimmmmmmmmmmmmmmmmmmmmmerです。

フロントエンド開発で重要になってくるprettierのプラグインvim-prettierを使用しているのですが、いかんせん上手く動かない。

題名どおりのエラーがjs/jsx/tsファイルで起き、prettierが動かないという自体が起きてました(tsxファイルだと何故か動く)。

代替えとしてdense-analysis/aleを使用している人がいたりいなかったり。

自分の方でもaleを使用してprettierを掛けるのですが、以下のように楽しいことになります。

f:id:rdwbocungelt5:20210826205030g:plain

これがマジでムカつく。

最近は色んな所でjsを触る機会が増えてきたため、いい加減直そうと思い調査に走りました。

調査

同じように悩んでる方がたくさんいるようでした。

github.com

github.com

github.com

issue内で書かれてるものを自分の方で試してみても全く効果はなかったのでライブラリのオプションを確認していくことに。

試したこと その1

prettierの入っているプロジェクト内で:PrettierCliPathで何が出てくるか確認。

これに関してはprettierと返ってきたのでプロジェクト内のprettierが実行されてるっぽい。

もしかしたら、vim-prettierのバグでプロジェクト内のprettierを認識できてない可能性がある…ということでglobalで使用しているprettierを使うようにオプション指定。

.vimrcに下記を追加。

# which prettierで出てきたやつを指定
let g:prettier#exec_cmd_path = '/home/motty/.asdf/shims/prettier'

:PrettierCliPathで上記パスが出てきたけど、:Prettierは上手くいかない…。

予想が外れたので次。

試したこと その2

これが正解でした。

何事も解決は公式が書いてるだろうと、vim-prettier本体のドキュメントを見に行くことに。

ローカルにあるprettier.txtを確認(自分のパスは/home/motty/.cache/dein/repos/github.com/prettier/vim-prettier/docでした)

と、自分の.vimrcで設定してある項目に目がつきました。

  " flow|babylon|typescript|css|less|scss|json|graphql|markdown or empty string
  " (let prettier choose).
  " default: ''
  let g:prettier#config#parser = ''

自分はparserをbabylonを指定してました。以前、vim-prettierが動かなかったときにbabylonを指定したら上手く行ったからです。かなり安直な考え。

もしや…と思いdefault状態に戻すことに。以下自分のvim-prettier設定です。

  " vim-prettier
  call dein#add('prettier/vim-prettier', {
       \ 'do': 'yarn install',
       \ 'branch': 'release/1.x',
       \ 'for': [
       \ 'javascript',
       \ 'typescript',
       \ 'typescriptreact',
       \ 'css',
       \ 'less',
       \ 'scss',
       \ 'json',
       \ 'graphql',
       \ 'vue',
       \ 'yaml',
       \ 'html'
       \]})
  let g:prettier#autoformat = 0
  let g:prettier#quickfix_enabled = 0
  let g:prettier#config#semi = 'false'
  let g:prettier#config#single_quote = 'true'
  let g:prettier#config#bracket_spacing = 'true'
  let g:prettier#config#parser = ''
  let g:prettier#exec_cmd_path = '/home/motty/.asdf/shims/prettier'
  " autocmd BufWritePre *.js,*.jsx,*.ts,*.tsx,*.vue,*.css,*.scss,*.json PrettierAsync

:Prettierを動かすと…


























うまくいったぁぁぁああああああああああああああああああああああああああああああああああ

つーか、babylonのリポジトリはすでに4年前に開発終了してましたね。

github.com

babelのモノレポ化前の名残らしく、今は@babel/parserとして開発されているそうです。そら動かんわ。

終わり

色んなものを定期的にメンテナンスしましょう。

今年中にvimrcの整理/toml化へ向けてがんばります。ALEのムカつく問題も残ってますしね。

【Golang】文字列が大文字かどうかの判定

f:id:rdwbocungelt5:20200720165613p:plain

どうもてぃ。

atcoder 第171回のA問題ででてきたので備忘録として。

atcoder.jp

TL;DR

package main

import (
    "fmt"
    "unicode"
)

func main() {
    var a string
    fmt.Scan(&a)
    r := rune(a[0])

    if unicode.IsUpper(r) {
        fmt.Println("A")
    } else {
        fmt.Println("a")
    }
}

詰まった点

値をrune型で受け取って上記のunicode.IsUpper()へ渡すと全てfalseになっちゃう

使ったpackage

func IsUpper(r rune) boolです。小文字を判定するなら func IsLower(r rune) boolがある。

pkg.go.dev

終わり

割とatcoderのA, B問題は言語の基礎を試すのにかなりいいですね。

知らないものがでてきたら今後もクソ記事書いていきたいと思います。

【Golang】mapを構造体へ割当(変換)する

どうもてぃ。

前回のつづきで備忘録。

smot93516.hatenablog.jp

mapと構造体を準備

type Addr struct {
    PostalCode int
    Country    string
}

type User struct {
    Name    string
    Age     int
    Address Addr
    Email   string
}

user := map[string]interface{}{
    "Name": "motty",
    "Age":  30,
    "Address": map[string]interface{}{
        "PostalCode": 1234567,
        "Country":    "japan",
    },
    "Email": "test@gmail.com",
}

構造体で定義した型に合わせてmapを作成してます。

map側の型と構造体の型が違った場合どうなるか…というのは後ほどやっていきます。

mapをjsonへ変換

encoding/jsonjson.Marshalを使用。

// mapをjsonへ変換
byte, err := json.Marshal(user)
if err != nil {
    fmt.Println(err)
    return
}
fmt.Println(string(byte))

こんな感じ。string(byte)の結果は以下。

{"Address":{"Country":"japan","PostalCode":1234567},"Age":30,"Email":"test@gmail.com","Name":"motty"}

json.Marshalの定義元を確認すると、

func Marshal(v interface{}) ([]byte, error) {
    e := newEncodeState()

    err := e.marshal(v, encOpts{escapeHTML: true})
    if err != nil {
        return nil, err
    }
    buf := append([]byte(nil), e.Bytes()...)

    encodeStatePool.Put(e)

    return buf, nil
}

と、最終的には[]byteerrorが返ってるので

byte, err := json.Marshal(user)

のようにerrも受け取って上げる必要がある。

とりあえず検証するだけ、エラーハンドリング不要であれば

byte, _ := json.Marshal(user)

として省くことも出来きます。

jsonを構造体へ

encoding/jsonjson.Unmarshalを使用。

// jsonを構造体へ割当
var u User
if err := json.Unmarshal(byte, &u); err != nil {
    fmt.Println(err)
    return
}

fmt.Println(u)

json.Unmarshalの定義元を確認。

func Unmarshal(data []byte, v interface{}) error {
    // Check for well-formedness.
    // Avoids filling out half a data structure
    // before discovering a JSON syntax error.
    var d decodeState
    err := checkValid(data, &d.scan)
    if err != nil {
        return err
    }

    d.init(data)
    return d.unmarshal(v)
}

Unmarshalの場合errorのみ返ってきて、第二引数に渡したポインタアドレスに第一引数で渡した値がスキャニングされてるっぽい(辿っていったけど詳しくはわからん)。

全部合わせたやつ

package main

import (
    "encoding/json"
    "fmt"
)

type Addr struct {
    PostalCode int
    Country    string
}

type User struct {
    Name    string
    Age     int
    Address Addr
    Email   string
}

func main() {
    user := map[string]interface{}{
        "Name": "motty",
        "Age":  30,
        "Address": map[string]interface{}{
            "PostalCode": 1234567,
            "Country":    "japan",
        },
        "Email": "test@gmail.com",
    }

    // mapをjsonへ変換
    byte, err := json.Marshal(user)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(byte))

    // jsonをstructへ割当
    var u User
    if err := json.Unmarshal(byte, &u); err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println(u)
}

実行結果

{"Address":{"Country":"japan","PostalCode":1234567},"Age":30,"Email":"test@gmail.com","Name":"motty"}
map[Address:map[Country:japan PostalCode:1234567] Age:30 Email:test@gmail.com Name:motty]

これをある程度理解していれば、簡単なwebサーバーは作れる。

サーバーを作るのはまた次回にするとして…

mapの型と構造体の型が異なる場合

たとえば以下のように構造体UserのAgeがint型であるにもかかわらず、map側がstringになっていた場合。

type Addr struct {
    PostalCode int
    Country    string
}

type User struct {
    Name    string
    Age     int
    Address Addr
    Email   string
}

user := map[string]interface{}{
    "Name": "motty",
    "Age":  "30",
    "Address": map[string]interface{}{
        "PostalCode": 1234567,
        "Country":    "japan",
    },
    "Email": "test@gmail.com",
}

何が起きるか、実行してみると

{"Address":{"Country":"japan","PostalCode":1234567},"Age":"30","Email":"test@gmail.com","Name":"motty"}
json: cannot unmarshal string into Go struct field User.Age of type int

jsonを構造体へ割当の部分、つまりjson.Unmarshal部分でエラーが返ってきます(しっかりしてんな)。

やってくるリクエスト(map)に対して構造体をしっかり用意してあげないと、今回のようにエラーが返ってくる…といった感じです。

mapと構造体でkey, valueの数が異なる場合

構造体で用意してある型とmapの型は一致しているが、mapの中身の要素数が異なる時どうなるか。

例えば、mapに"Test": "test"というkey, valueが入っていたとき

type Addr struct {
    PostalCode int
    Country    string
}

type User struct {
    Name    string
    Age     int
    Address Addr
    Email   string
}

user := map[string]interface{}{
    "Name": "motty",
    "Age":  30,
    "Address": map[string]interface{}{
        "PostalCode": 1234567,
        "Country":    "japan",
    },
    "Email": "test@gmail.com",
    "Test": "test",
}

こういう場合、最終的にはエラーは出ず構造体側が優先されます。

json.Unmarshalされたとき、構造体にないものは割り当てられないという認識でいると良いです。

もし"Test"を受け取りたいなら、構造体側にちゃんと型を定義してあげましょう。

最後に

Goは楽しいですよ。

次回は構造体→mapを書こうと思います。

【Golang】mapを作る

どうもてぃ。

ルビーやジャヴァスクリプトをやっていると毎回間違えるのでメモ。

対応関係

言語
ruby hash = {}
go map := map[string]interface{}
js object = {}

大まかに分類するとこんな感じ。

ただ、goの場合型を指定するため、対応する型以外はmapの中に入れられないです。rubyやjsのように動的にしたいなら…

map := map[interface{}]interface{}{}

と宣言すればよいですが、これだと型の恩恵がないのでほとんど使わない。

goやってるのならgoしましょう。

宣言方法

空のmap

// その1(明示的に書く)
var hoge map[string]int = map[string]int{}

// その2(makeを使う)
huga := make(map[string]int)
huga2 := make(map[string]int, 10) // 領域を確保して作成可能

// その3(簡略化)
hogo := map[string]int{}

そもそもmapを作成するのであれば、ある程度中身の構造が決まっているので構造体を使用することが多い。

が、その中でもその3の使用率が高いですね。

中身ありのmap

上とほとんど一緒かも。

// 明示的に
var foo map[string]string = map[string]string{"go": "hello echo", "ruby": "hello rails", "javascript": "hello react"}

// 簡略
bar := map[string]string{"go": "hello echo", "ruby": "hello rails", "javascript": "hello react"}

// 上の改行版
yoo := map[string]string{
  "go": "hello echo",
  "ruby": "hello rails",
  "javascript": "hello react",
}

// キー指定の代入
hash := make(map[string]string)
hash["go"] = "hello echo"
hash["ruby"] = "hello rails"
hash["javascript"] = "hello react"

最後に

もう忘れない(たぶん)。

次はmap[string]interface{}から構造体へ変換、またその逆もまとめる予定。

【備忘録】Next.js × TypeScriptのセットアップメモ

どうもてぃ。

毎回eslint/prettierの設定をやり直すのクソだるいのでメモしときます。

環境

  • node v15.12.0

プロジェクト作成

next v11だと標準でeslintの設定が入るみたいですね。メチャ楽になったな。

# 自分はこれだとeslintが入らなかった…
$ npx create-next-app <project-name> --typescript

or

$ yarn create next-app <project-name> --typescript

package.jsonの中身がこんな感じ。

{
  "name": "project-name",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "next": "11.0.1",
    "react": "17.0.2",
    "react-dom": "17.0.2"
  },
  "devDependencies": {
    "@types/react": "17.0.14",
    "eslint": "7.31.0",
    "eslint-config-next": "11.0.1",
    "typescript": "4.3.5"
  }
}

GitHub Repositoryの作成

これはおまけ

$ gh repo create <project-name>

github cliが入ってないと無理なのでご注意を。

tsconfig.jsonの設定

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "noImplicitAny": true,
    "baseUrl": "./",
    "paths": {
      "~/*": ["./*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
  "exclude": ["node_modules"]
}

noImplicitAny, baseUrl, paths を追加しただけ。

eslint設定

package.jsonみたらわかりますが、最初から入ってます。

.eslintrcの中身がこれ。

{
  "extends": ["next", "next/core-web-vitals"]
}

prettier設定

.prettierrc.jsをプロジェクトルートに作成。

module.exports = {
  jsxBracketSameLine: true,
  singleQuote: true,
  trailingComma: 'all',
  semi: false,
  printWidth: 110,
  tabWidth: 2,
  parser: 'typescript',
  overrides: [
    {
      files: '*.json',
      options: {
        parser: 'json',
      },
    },
  ],
}

その他必要なもの

babel-plugin-module-resolver導入

$ yarn add -D babel-plugin-module-resolver

babelrc.jsをプロジェクトルートに作成

module.exports = {
  presets: ['next/babel'],
  plugins: [
    [
      'module-resolver',
      {
        root: ['.'],
        alias: {
          '~': './',
        },
      },
    ],
  ],
}

autoprefixer導入

$ yarn add autoprefixer

axios導入

$ yarn add axios

ReduxToolkit導入

state管理はReduxToolkitを使用。

$ yarn add @reduxjs/toolkit

終わり

最終的な package.jsonがこちら。

{
  "name": "microcms-next-blog",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@reduxjs/toolkit": "^1.6.1",
    "autoprefixer": "^10.3.1",
    "axios": "^0.21.1",
    "next": "11.0.1",
    "react": "17.0.2",
    "react-dom": "17.0.2"
  },
  "devDependencies": {
    "@types/react": "17.0.14",
    "babel-plugin-module-resolver": "^4.1.0",
    "eslint": "7.31.0",
    "eslint-config-next": "11.0.1",
    "typescript": "4.3.5"
  }
}
$ yarn dev

f:id:rdwbocungelt5:20210718141058p:plain