サカナ未遂

プログラミング、筋トレ、子育て

独習Ruby on Railsを読んだ

こないだ現場Railsを読んだら、Railsに知らないことや忘れてるところが結構あった。 blog.tera-chan3700.com

一応業務でRails触ってるけど、既存コードの改修だったりでなんとなくこなせていたけど、業務で使ってる以上のことが全然成長してないので、まだまだ基礎的なとこ固めようと思い、今度は独習Ruby on Railsを読むことにした。

独習Ruby on Rails

独習Ruby on Rails

  • 作者:小餅 良介
  • 発売日: 2019/06/19
  • メディア: 単行本(ソフトカバー)

3章までは、軽く読んだのでまとめてない。 4章以降で初めて知ったことなどメモしておく。

4章

rails dbconsole(rails db)

実装されてるDBのコマンドラインツールを起動してくれる。 SQLite3/MySQL/PostgreSQLの3種類が対象。 --sandboxオプションは使用できない。

rails stats

現在のアプリケーションのRubyコード統計情報を表示するコマンド。

rails notes

ソースコードに埋め込んだコメントの中からTODO、FIXME、OPTIMIZEのキーワードがあるものを抽出し内容と場所を一覧で表示してくれる。

6章

フォームオブジェクト

現場Railsでもちょっとだけ記載があったフォームオブジェクト。 特定のモデルに限定されないか、DBの登録に直接関係ない入力のバリデーションは入力専用のオブジェクト(フォームオブジェクト)を使うことで整理ができる。 利用承諾など、チェックボックスだけがあり、対応するモデルがない場合などに使える。 app/forms/acceptance.rb みたいな感じでファイルを作成し、ActiveModelを継承させることでバリデーションの機能を実装することができる。

Validateクラスで共通の独自ヘルパーを実装

app/validators配下にActionModel::EachValidatorを継承したクラスを作り、validate_eachを実装することでモデル共通のバリデーションを作成することができる。 バリデーションをまとめることができるのは知らなかった。

コールバッククラスの共通化

バリデーションと同様コールバックも共通化できる。 app/callbacks配下にクラスを作成し、中にバリデーションの処理を実装する。

class MessageOut
  def self.before_validation(obj)
    # バリデーション処理
  end
end

呼び出し側

class Book < ApplicationREcord
  before_validation MessageOut

  ....
end

こんな感じ。

7章

ポリモーフィック関連

子モデルで複数の親モデルを持つ時にポリモーフィック関連を使う。 userモデル、bookモデルを親に持つpictureモデルを作る場合、以下のようにmigrationファイルを作成

class CreatePictures < ActiveRecord::Migration[6.1]
  def change
    create_table :pictures do |t|
      t.references :imageable, polymorphic: true
      t.string :path_name

      t.timestamps
    end
  end
end

db:migrationするとPictureモデルは以下のようになる

class Picture < ApplicationRecord
  belongs_to :imageable, polymorphic: true
end

各親モデルにPictureモデルへの関連と行う。 bookモデル

class Book < ApplicationRecord
  has_many :pictures, as: :imageable
end

userモデル

class User < ApplicationRecord
  has_many :pictures, as: :imageable
end

こうすることによって、PictureはUserとBookを親に持つことができる。

仮想属性

テーブルカラムを持たない仮想的な属性(attributes API)を作ることができる。 Addressモデルに対してattributeを追加することで使用できる。

class Address < ApplicationRecord
  attribute :location, :string, default: '東京都葛飾区'
end

8章

コレクションルートとメンバールート

  • コレクションルート 複数のリソースを対象とするルートかidを持っていない新規リソースに対するルート

  • メンバールート idパラメータで特定できるルート

shallowルート

親子関係にあるリソースで子リソースをidで一意に特定できる場合、子のIDだけでアクセスできるようにするのにshallowを使う。

shallow do
  resources :user do
    resources :hobbies
  end
end

または

resources :users, shallow: true do
  resources :hobbies
end

のように設定する。

リソースフルルートのグループ化

名前空間によるリソースルートのグループ化を行った場合、名前空間はコントローラのファイルが配置されるディレクトリ名に相当する。 なのでコントローラは「名前空間名」ディレクトリに移動させる必要がある。

リソースルートだけをグループ化したい場合はscopeメソッドを使う。 scopeの場合だとコントローラの配置移動の必要はない。

ルートの共通化

同じ目的のルートパス名を複数で使用する場合は、concernを使うことで共通化できる。

# 共通ルート
concern :searchable do
  get 'search', on: :collection
end

# 各リソースフルルートで共通ルートを紐付ける
resources :user,s concerns: :searchable
resources :books, concerns: :searchable

9章

respond_toメソッド

リクエストされるフォーマットによてレスポンスを柔軟に変更することができる。

def show
  @user = User.find(params[:id])
  respond_to do |format|
    format.html
    format.json {render json: @user}
  end
end

上記のコードの場合

  1. http://localhost:3000/users/1
  2. http://localhost:3000/users/1.json

で1の場合html、2の場合jsonでレスポンスを返してくれる。

10章以降

viewに関するとことか、とりあえず直近の業務では触ることないのでサラッと読んで終わり。 必要な時が来たら読み直そうと思う。

所感

現場Railsを読んだばかりだし同じような内容の箇所は飛ばして読んだが、 一つ一つの機能がより細かく説明されている。特に章末の練習問題がためになる。 写経だけしてプログラム動かすとできた気になるが、練習問題で自分で考えてコード書くとやっぱり身に付く。 scaffoldでさえ本見ないと、どうやるんだっけ?となってるので良い機会だった。 同じ技術の本を続けて読むと、1冊目は結構時間かかるけど、2冊目以降はある程度知ってる箇所飛ばして知らないとこにフォーカスできるので、この流れで次はパーフェクトRuby on Raisを読んでみようかと思う。

Railsで共通で使用できるバリデーションを作る

Railsのモデルに独自のバリデーションを作成する時、以下のように実装する

class User < ApplicationRecord
  validate :email_check

  private

  def email_check
    # Eメールのバリデーション処理
    .....
  end
end

この場合、Userモデル限定のバリデーションとなる。 特定のオブジェクトに限定されずに共通で使用できるバリデーションを作成するには app/validatorsディレクトリの下に、新しいクラスを作成しvalidate_eachメソッドを実装する。

#app/validators/email_address_validator.rb
class EmailAddressValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
      record.errors[attribute] << (options[:message] || "はメールアドレスではありません")
    end
  end
end

# 各クラスで使用できる。
class Person < ApplicationRecord
  validates :email, presence: true, email_address: true
end

class User < ApplicationRecord
  validates :email, presence: true, email_address: true
end

validate_eachの第一引数recordは、呼び出し側のオブジェクト、第二引数attributeは指定した属性名、第三引数valueは指定した属性の値が入る。

呼び出し側で、email_address: trueとすることで、ValidateクラスがEmailAddressValidatorであることを示すことになる。

参考書籍に

独習Ruby on Rails

独習Ruby on Rails

  • 作者:小餅 良介
  • 発売日: 2019/06/19
  • メディア: 単行本(ソフトカバー)

現場で使えるRuby on Rails 5 速習実践ガイドを読んだ

積読していた現場Railsを読みました。

全部読むの結構時間かかったけど、知らなかったこと、忘れていたこと結構あったのでそれらをまとめまた。

Chapter1

1-7 読めると便利! Rubyっぽい書き方

この辺りのイディオム、ちょくちょく見るし便利だけどいつも忘れる。

nilガード

number ||= 10

# number || (number = 10) と同じ動き

numberに値が入っていればそのまま、nilなら10を代入する。

ぼっち演算子

&.をつけてメソッドを呼び出すとレシーバがnilでもエラーが発生しない。

obj = nil

# objはnilなのでeachを使おうとするとエラーになる。
obj.each{|x| puts x }
NoMethodError: undefined method `each' for nil:NilClass

# ぼっち演算子をつけるとエラーにならない
obj&.each{|x| puts x }
=> nil

%記法

# %wは文字列の配列を生成する
%w(foo bar piyo)
=> ["foo", "bar", "piyo"]

# %iはシンボル の配列を生成する
%i(foo bar piyo)
=> [:foo, :bar, :piyo]

Chapter3

slimを使う。

下記を追加することで、slimが使える

gem 'slim-rails'
gem 'html2slim'

コマンドを実行することで既存のファイルをslimに変換してくれる

 bundle exec erb2slim app/views/layouts/ --delete

現職ではvueを使ってるので、slim使ったことなかった。pugみたいなもんか。

i18nでエラーメッセージを日本語にする

下記コマンドでja.ymlを取得してconfig/localesにおく。

wget https://raw.githubusercontent.com/svenfuchs/rails-i18n/master/rails/locale/ja.yml --output-document=config/locales/ja.yml

config/initialilzers/locale.rbに以下を記載する。

Rails.application.config.i18n.default_locale = :ja

リクエストパラメータ

GETでもPOSTでもパラメータの受け取り方をプログラマが区別しなくていいようにparamsが使える。 なんとなく使ってたけど、確かにGETでもPOSTでも同じように使えるのはRailsがやってくれてたのか。

レンダーとリダイレクト

レンダーはアクションに続けてビューを表示すること。リダイレクトはアクションを処理した直後にビューを表示せず別のURLに案内すること。

simple_format

以下のコード、hメソッドでXSS対応をした上で改行を
に変換し、さらに

タグで囲んでくれる。

simple_format(h(@task.description), {}, sanitize: false, wrapper_tag: "div")

Chapter4

バージョンを1つ戻してから1つ上げる。 バージョンが戻ることの確認とかに使う。

bin/rails db:migrate:redo

マイグレーションファイルのupとdown

マイグレーション失敗時に自動で戻せない場合に必要。 add_columnとかの場合の失敗は自動で戻してくれるから不要だけど、カラムにlimit: 30とか追加する時にはdownも書いておくと戻せる。downがないと例外が発生する。

validateのスキップ

falseを設定することでvalidateをスキップできる。

task.save(validate: false)

persisted?メソッド

オブジェクトがDBに登録されているかどうか確認ができる。

redirect_toのパラメータにmodelのオブジェクト

redirect_toのパラメータにmodelオブジェクトすると、showのページに遷移する。

validatesとvalidateの違い

標準の検証はvalidatesで自前の検証処理はvalidateになる。

パスワードのハッシュ化

has_secure_passwordを使うことでパスワードをハッシュ化できる。 使うにはbcrypt(gem)が必要。 has_secure_passwordをモデルに記述すると、passwordとpassword_confimartion属性が追加される。 2つの属性が一致した時だけパスワードを登録することができる。 テーブルにはpassword_digestの名前でカラムを用意しておく必要がある。これはhas_secure_passwordを使用するときの命名ルールである。

認証のためのauthenticate

authenticatehas_secure_passwordを記述した時に自動で追加される認証のためのメソッド。引数で受け取ったパスワードをハッシュ化して、オブジェクトに保存されてるdigestと一致するか調べる。

helper_method

コントローラにhelper_methodでメソッドを定義すると、viewからでも呼び出すことができる。

skip_before_action

before_actionをスキップすることができる。

Chapter5

Rspecについて

Rspecは動く仕様書として自動テストを書くという発想で作られてる。Rspecは「テスト」ではなく「Spec」を書くという気持ちが大事とある。 「動く仕様書」か、なるほどなるほど。 とりあえず書くもんだと今まで書いてきたけど、こういうフレームワークの思想みたいなものを知ることで、納得してテストを書いていける。

SystemSpecについて

FeatureSpecの代わりっぽい?、結局SPAでどうやるのか?と調べたらいけそう。 ここを見てみた。 tech.unifa-e.com

弊社ではE2EはRequestSpecしか書いてなかったけど、SystemSpecも導入した方が良いのかな。

visit

特定のURLでアクセスする。ログイン画面にアクセスする場合とかは以下のように記述する。

visit login_path

fill_in

パラメータで指定したラベルがついたテキストフィールドに値を入れる。 以下のように記述する

fill_in 'メールアドレス', with: 'a@example.com'

shared_examples_for

itなどを共通化することができる。

shared_examples_for 'タスクが画面に表示されること' do
  it { expect(page).to have_content 'タスク' }
end

コンソールのサンドボックス

Railsコンソールにサンドボックスあるの知らなかった〜。-s付ければいいのか

bin/rails c -s

Chapter6

CSRFはシーサーフと読まれることがある。

SQLインジェクションに気を付けるパターン

whereメソッドなどでSQL文字列を直接渡して条件指定するときはSQLインジェクションに気を付ける。 こんな場合

User.where("name = '#{params[:user_name]}'")

こっちにした方がいい。

User.where('name = ?', params[:user_name])

プレースホルダを使うと、「'」とかをエスケープしてくれる。

Chapter7

ransackを使うときに気を付けること

modelに以下のコードを入れることで特定のカラムに対してしかクエリーを発行できないようにすることができる。 下のコードは関連を指定できる。[]にすることで意図しない関連を含めないようにする。

def self.ransackable_attributes(auth_object = nil)
  %w[name created_at]
end

def self.ransakable_associations(auth_object = nil)
  []
end

mailcatcher

mailcatcherは送信したメールをブラウザ上で確認することができるgem コンソールから以下のコマンドで使える

mailcatcher

config/environments/development.rbに以下の設定をすると使える

config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = { address: '127.0.0.1', port: 1025 }

ActiveStorage

クラウドサービスにファイルをアップロードしてActiveRecordモデルに紐付けることが簡単にできる。 config/storage.ymlに保存先を設定する。 コメントアウトされているが、AWSやGCSも簡単に設定できる。

Chapter9

redoを習慣にする。

ロールバックできないトラブルを防ぐためにマイグレーションを書いたとき、ロールバックが成功することを確認することが重要。

マイグレーションファイルからアプリケーションコードの参照は避ける。

マイグレーションコードは積み重なっていくのでいつ実行しても同じように動く必要がある。 アプリケーションコードを使用する場合、その内容が変更(モデルにバリデーションが追加されるなど)したらマイグレーションファイルの挙動も変わってしまうため、避けた方が良い。

スキーマキャッシュ

マイグレーションファイルでモデルインスタンスを作成すると、ActiveRecordスキーマをキャッシュする。同じテーブルに対して連続してマイグレーションを行う場合、キャッシュが効いて意図しない挙動になることがあるので、reset_column_informationスキーマキャッシュを更新するよう習慣づける必要がある。

Chapter10

共通機能のモジュールのMix-in

RailsでMix-inのモジュールを書く時にはActiveSupport::Concernをextendする。 クラスレベルの拡張を素のrubyに比べて少し書きやすくしてくれる。

SIT

ActiveRecordモデルの継承する場合、継承元と継承先で1つのテーブルに対応づけを行うことをSIT(Single Table Inheritance)と呼ぶ。 対応づけらえるテーブルには継承されたテーブルが必要とするカラムを全部盛り込む必要がある。

複数のモデルがカラム処理は特定処理の専門家を作る

コントローラで2つのモデルを扱う処理の場合、片方のモデルにコードを書くと、他のモデルのデータの依存性を高めるのでよくない。 2つのモデルのデータを扱う専門のクラスを作成して処理を書くと良い。

サブリソース単位でコントローラを分割

コントローラは1つのモデルに対して1つでなければならないわけではない。 サブリソースへの操作を対応する複数のコントローラに分けることができる。

所感

まとめて感じたのは特にviewで使う機能に関する知識が結構欠落していること。 SPAがスタンダードになりつつあるので出番が減ってるのは確かだが、Railsを使って仕事をしていくなら最低限は覚えておかないとなぁとしみじみ思う。 あと、Chapter10は現場でかなり参考になる情報だった。定期的に読みなそうと思う。 いつ買ったのかAmazonの購入履歴で調べたら、買ってから2年も経ってた、、、もっと早く読んどけば良かった。 今年は積読消化を頑張らないと

JavaScriptのawait式をAsync Functionの中で使用するときの注意点

JavaScriptのPromiseとかawaitとか雰囲気で乗り切ってきたけど、ちゃんと腰据えて勉強しようと思って購入したJavaScript Primer

非常に分厚いけど、読みやすくサンプルコードも豊富なので理解しやすかった。 まだまだ全部よめてないけど、非同期処理のところを集中的に読む。

第22章で気をつけないとと思った箇所

async function asyncMain(){
  await new Promise((resolve) => {
    setTimeout(resolve, 16); 
  });
};

console.log("1. asyncMain 関数を呼び出します");
asyncMain().then(() => {
  console.log("3. asyncMain関数が終了しました。");
});
console.log("2. asyncMain 関数外では次の行が同期的に呼び出される");

このコードを実行した場合、asyncMainでawaitをつかって処理をとめているけど、関数を呼び出してるメインの処理はとまらず最後のconsole.logを出力する。 あくまで関数の中ではとまっているだけである。 awaitで何でも止めれると思っていたので知ることができてよかった。

CloudRunを使ってみた

GCPのCloudRunというサービスを使うことがあったので簡単な使い方をメモっときます。

CloudRunとは

公式URLより https://cloud.google.com/run?hl=ja

コンテナ化されたアプリケーションをすばやく安全にデプロイ、スケーリングできる、フルマネージド型のコンピューティング プラットフォーム

とあります。 コンテナに入れたwebアプリを、そのままデプロイできるってことですね。 GCPのContainerRegistoryにコンテナをpushし、CloudRunでデプロイするだけで動かせます。

CloudRunの料金

https://cloud.google.com/run/pricing?hl=ja f:id:tera_chan3700:20200618212128p:plain

ちょっと試すくらいならほぼ無料で使えます。

あとContainerRegistoryの料金がかかりますが、これも微々たるものです。 https://cloud.google.com/container-registry/pricing?hl=ja 個人で試すには懐が痛まなくて好きそうです。

注意

CloudRunからCloudRun、または他のサーバレスを無限ループで呼ぶような処理があると危険です。そこは個人で気をつけてください。 例:https://blog.mmmcorp.co.jp/blog/2019/12/25/lambda-cloud-bankruptcy/ これはAWSですが、GCPでも起こりえます。

サンプル

GOで簡単なエコーサーバーを作ります

package main

import (
    "fmt"
    "log"
    "net/http"
    "net/http/httputil"
)

func handler(w http.ResponseWriter, r *http.Request) {
    dump, err := httputil.DumpRequest(r, true)
    if err != nil {
        http.Error(w, fmt.Sprint(err), http.StatusInternalServerError)
        return
    }
    fmt.Println(string(dump))
    fmt.Fprintf(w, "<html><body>hello Cloud Run!!!</body></html>")
}

func main() {
    var httpServer http.Server
    http.HandleFunc("/", handler)
    log.Println("start http listening :8080")
    httpServer.Addr = ":8080"

    log.Println(httpServer.ListenAndServe())
}

8080ポートにアクセスすると、「hello Cloud Run!!!」の文字列を返すサーバーです。 実行して確認します。

$ go run main.go
2020/06/18 20:01:04 start http listening :8080

サーバーが起動したのでアクセスしてみる f:id:tera_chan3700:20200618213242p:plain

レスポンスが帰ってきました。

次にこれをビルドして実行するDockerfileを作ります。

FROM golang:latest

#ディレクトリ作成
WORKDIR /go/src/go-image
#ホストOSのmain.goをWORKDIRにコピー
COPY main.go .

#バイナリを生成
RUN go install -v .

#バイナリを実行
CMD ["go-image"]

これをビルドします。

$ docker build -t gcr.io/<自分のプロジェクトID>/cloudrun-test:v1 .

ローカルで実行してみます

$ d run -p 8080:8080  gcr.io/<自分のプロジェクトID>/cloudrun-test:v1

アクセスします。 f:id:tera_chan3700:20200618213636p:plain 動きました。ちゃんとコンテナの中で起動することが確認できました。

コンテナレジストリへのpush

今回はステージングをかります。 gcloudコマンドで事前にログインしています。

GCPにpushする。

docker push gcr.io/<自分のプロジェクトID>/cloudrun-test:v1

入ったことを確認 f:id:tera_chan3700:20200618213808p:plain

CloudRunへのデプロイと実行

サービスを作成をクリック f:id:tera_chan3700:20200618213957p:plain

適当に入力して「次へ」をクリック f:id:tera_chan3700:20200618214119p:plain

さっきpushしたイメージを選択して作成ボタンをクリック f:id:tera_chan3700:20200618214315p:plain

しばらくするとデプロイが完了し、エンドポイントが作成されます。 f:id:tera_chan3700:20200618214521p:plain

ここにアクセスします。 f:id:tera_chan3700:20200618214609p:plain

動きました。 ローカルで作ったコンテナが簡単にデプロイでき、動かすことができます。 タイムアウトなど制限もありますが、ローカルで動いてるコンテナを簡単にデプロイできるのは便利です。

gRPCについて学んだこと

会社の業務でgRPC触ることがあったのですが、そもそもRPCってなんぞやって状態でしたので、勉強してみることにしました。

まずgRPCを勉強しようと思った時に、不明な用語があったのでそれらを整理してから進めることにしました。  

RPCとは

まずRPCは、Remote Procedure Call(遠隔手続き呼び出し)の略で、プログラムから別のアドレス空間にあるサブルーチンや手続きを実行することを可能にする技術のこと。

でgRPCは、Google社内で使われていたRPCフレームワークOSS化され、gRPCと名前がついたもののことだそうです。 ちなみにgRPCのgはGoogleのgではないです。バージョン毎にいろいろg縛りの言葉がついてるようです。 ここに書いてた GRPC Core: g_stands_for

Protocol Buffersとは

gRPCはデータをProtocol Buffersにシリアライズしてやりとりを行う。 Protocol BuffersもGoogleが開発したフォーマットで、XMLとの比較で、3〜10倍小さく、20〜100倍高速であると主張しているとのこと。

ProtocolBuffersは、protoファイルを作成します。 ファイルをコンパイルすると任意の言語用のコードを自動で作成してくれます。 GoやRubyなど様々な言語に対応しています。 現在はproto3です(いつから3なのか、2との違いは何なのかちゃんと調べてない)

試してみる

公式のチュートリアルの通りにやってみる。 まずサンプルをダウンロードし、ディレクトリ移動

$ git clone -b v1.28.1 https://github.com/grpc/grpc
$ cd grpc
$ cd examples/ruby

サーバーを起動する。

$ ruby greeter_server.rb

別のターミナルでクライアントを起動

$ ruby greeter_client.rb
# 結果が帰ってくる
"Greeting: Hello world"

どういう仕組みかコードを確認。

まずgreeter_client.rb

# GreeterServer is simple server that implements the Helloworld Greeter server.
class GreeterServer < Helloworld::Greeter::Service
  # say_hello implements the SayHello rpc method.
  def say_hello(hello_req, _unused_call)
    Helloworld::HelloReply.new(message: "Hello #{hello_req.name}")
  end
end

# main starts an RpcServer that receives requests to GreeterServer at the sample
# server port.
def main
  s = GRPC::RpcServer.new
  s.add_http2_port('0.0.0.0:50051', :this_port_is_insecure)
  s.handle(GreeterServer)
  # Runs the server with SIGHUP, SIGINT and SIGQUIT signal handlers to 
  #   gracefully shutdown.
  # User could also choose to run server via call to run_till_terminated
  s.run_till_terminated_or_interrupted([1, 'int', 'SIGQUIT'])
end

mainでRPCサーバーを0.0.0.0:50051で起動しハンドラーにGreeterServerを設定している。 GreeterServersay_helloというメソッドを持ち、 Helloworld::HelloReply.new(message: "Hello #{hello_req.name}")(これはhelloworld_services_pb.rbに定義されていた。) を実行する。 Hello + リクエストのnameプロパティの値を返す

クライアント側

def main
  stub = Helloworld::Greeter::Stub.new('localhost:50051', :this_channel_is_insecure)
  user = ARGV.size > 0 ?  ARGV[0] : 'world'
  message = stub.say_hello(Helloworld::HelloRequest.new(name: user)).message
  p "Greeting: #{message}"
end

gRPCのスタブを生成し、say_helloメソッドに"world"を渡す。 サーバから帰ってきたメッセージにGreetingを付加して出力している。

所感

まずはこんな感じってのがわかった。 クライアントからサーバーのメソッドを呼び出すという概要は理解できた。 チュートリアルの最初の最初をやっただけなので、protoファイルの作り方やストリーミング など、もっと学習していこうと思います。

参考にさせていただいた資料

booth.pm

grpc.io

k8sで複数環境を触るときに便利なツール

kubernetesで操作する環境が増えてくると、想定外の環境にデプロイするような事故が増えてくるので、少しでも事故を減らすためのツールを紹介します。

kubectx

コンテキストを簡単に切り替えてくれるツール

インストール

$ brew install kubectx

コンテキスト切り替え

# 特定の環境に切り替え
$ kubectx gke_my-project-development_asia-northeast1-a_sample-cluster

、、、、コンテキストが長い…

別名をつけることができる。

$ kubectx MYDEV=gke_my-project-development_asia-northeast1-a_sample-cluster

これで、別名で切り替えることができる。

# 開発環境に切り替え
$ kubectx MYDEV
# 本番に切り替え(本番の別名をつけておく)
$ kubectx PROD

kube-ps1

実行中のコンテキストをプロンプトに表示させることができる。 https://github.com/jonmosco/kube-ps1

インストール

$ brew install kube-ps1

.bashrcの設定

# .bashrc
PS1='\u:\W\$'   # プロンプト表示を、ユーザ名とカレントディレクトリのみにしている(ここは各自の好みで)
source "/<インストールパス>/kube-ps1/share/kube-ps1.sh"
PS1='$(kube_ps1)'$PS1
kubeoff      # デフォルトでオフにしておく
# 表示
$ kubeon

# 非表示
$ kubeoff

こんな感じで表示される

$ kubeon
# ステージングに切り替え
$ kubectx STAGE
(⎈ |STAGE:default)username:workspace$

# 本番に切り替え
$ kubectx PROD
(⎈ |PROD:default)jusername:workspace$

$ kubeoff
username:workspace$

これで自分が操作中のコンテキストを確認しながら作業できるので、少しは安全になります。