DevOpsを推進するうえでチェックした資料まとめ

概要

最近DevOpsを推進する活動をしていたので、チェックした資料をまとめる。

『Effective DevOps』

Effective DevOps ―4本柱による持続可能な組織文化の育て方

Effective DevOps ―4本柱による持続可能な組織文化の育て方

DevOpsの文化、概念について書かれている。
組織が陥りがちなアンチパターンについても網羅されている。
エンジニアとして働いているとついツールや手法の方に目が行きがちだが、文化や概念を抑えておくと、手段と目的が逆になるのを防げてよい。

AWS

AWSでは下記ページでDevOpsの概念からツールまで一通り網羅されている。
DevOps とは? - DevOps と AWS | AWS
AWSではグラレコを用いた資料があるので、視覚的にわかりやすく、非エンジニアに説明するときに参考にすると良い。
AWS でデプロイの自動化を実現するベストプラクティスをグラレコで解説 - builders.flash☆ - 変化を求めるデベロッパーを応援するウェブマガジン | AWS
定期的に更新さているブログもある。
AWS DevOps Blog

GCP

GCPの資料ではアーキテクチャについて言及されている。
また、DevOps Research and Assessment(DORA)のレポートやホワイトペーパーがまとまっている。
What is DevOps? Research and Solutions  |  Google Cloud
GCPはかんたんな技術的チェックに答えると、業界平均と比べどの程度か把握することができる。
DORA DevOps Quick Check

Azure

Azureはチェックリストを公開している。
ここでも文化のほうが先に書かれており、ツールだけの話でないことが表されている。
DevOps とは何ですか?DevOps の説明 | Microsoft Azure
DevOps checklist - Azure Design Review Framework | Microsoft Docs
また、『Effective DevOps』やDevOpsに関するレポートがダウンロードできるようになっている。
Azure DevOps Services | Microsoft Azure

『Release It!』

この書籍にはDevOpsという言葉は出てこない。
しかし、ソフトウェアをリリースするにあたり気にしたほうがいいことについて、豊富な実例とともに書かれている。
実装、設計、運用と実際のソフトウェア開発の内容にフォーカスしている。
内容は少し古いが読み物として面白かった。

まとめ

DevOpsに関して、複数の資料を読むと共通して書かれている大事なことが見えてくる。
特にツールに関しては見知ったものが多かったが、組織活動・文化の重要性を説いた資料が多かった。 今回あげたものの中で上から『Release It!』を除いた4点の資料をおさえておくと良い。

Goのドット3つ

概要

Goを書いているときに見るドット3つについて公式ドキュメントのリンクをもとにコード例を示す。

配列

https://golang.org/ref/spec#Composite_literals

The notation ... specifies an array length equal to the maximum element index plus one.

とあるように下記の例だとdaysのインデックスが[0,1]であり、最大のインデックス1に1を追加して2となる。

package main

import (
    "fmt"
)

func main() {
    days := [...]string{"Sat", "Sun"}  
    fmt.Println(len(days)) //2
    arr := [2]string{"foo", "bar"}  
    fmt.Println(len(arr))  //2
}

可変長引数

https://golang.org/ref/spec#Passing_arguments_to_..._parameters
複数の引数を渡したいときは下記のように書く。

package main

import (
    "fmt"
)

func main() {
    Greeting("nobody")                          //nobody
    Greeting("hello:", "Joe", "Anna", "Eileen") //hello:Joe Anna Eileen
    s := []string{"James", "Jasmine"}
    Greeting("goodbye:", s...) //goodbye:James Jasmine
    // Greeting("goodbye:", s) //cannot use s (type []string) as type string in argument to Greeting

}

func Greeting(prefix string, who ...string) {
    fmt.Printf("%s", prefix)
    for _, val := range who {
        fmt.Printf("%s ", val)
    }
    fmt.Println()
}

スライスの追記とコピー

https://golang.org/ref/spec#Appending_and_copying_slices

package main

import (
    "fmt"
)

func main() {
    s0 := []int{0, 0}
    s1 := append(s0, 2)              // append a single element     s1 == []int{0, 0, 2}
    s2 := append(s1, 3, 5, 7)        // append multiple elements    s2 == []int{0, 0, 2, 3, 5, 7}
    s3 := append(s2, s0...)          // append a slice              s3 == []int{0, 0, 2, 3, 5, 7, 0, 0}
    s4 := append(s3[3:6], s3[2:]...) // append overlapping slice    s4 == []int{3, 5, 7, 2, 3, 5, 7, 0, 0}
    fmt.Println(s4)

    var t []interface{}
    t = append(t, 42, 3.1415, "foo") //                             t == []interface{}{42, 3.1415, "foo"}

    var b []byte
    b = append(b, "bar"...) // append string contents      b == []byte{'b', 'a', 'r' }

}

JavaScriptでマイク、カメラが使用されているか確認する

Webブラウザでマイクやカメラなどのデバイスが使用されていたらtrueを返す

await navigator.mediaDevices.enumerateDevices().then(infos => [...infos].some(info=>info.label!==""));

マイクやカメラの許可状態を確認する

await  navigator.permissions
    .query({ name: "camera" })
    .then(function (permissionStatus) {
      console.log(permissionStatus.state);
    });

参考

JavaScriptを使用してGoogle Chromeで開いているすべてのタブの情報を取得する

chrome extension APIを使って、開いているすべてのタブを取得する

test.js

  chrome.tabs.query({}, function (tabs) {
    console.log(tabs);
  });

manifest.json

{
   ...
  "permissions": [
    "tabs"
  ],
  ...
}

参考

https://developer.chrome.com/extensions/tabs

.envで定義した環境変数をDocker,docker-compseで使用する例

.envからdockerの実行環境に環境変数を渡す例

環境

go1.13.8
Docker version 19.03.8

ディレクトリ構成

Dockerfile
docker-compose.yaml
go.mod
main.go
.env
.env2

main.go

package main

import (
    "fmt"
    "os"
)

func main() {
    fmt.Println("hello world")
    fmt.Println(mustGet("TEST"))
}

func mustGet(arg string) string{
    env := os.Getenv(arg)
    if env == ""{
        panic("env not found")
    }
    return env
}

Dockerfile

FROM golang:latest
WORKDIR /app
COPY go.mod ./
RUN go mod download
COPY . .
RUN go build -o main .
CMD ["./main"]

docker-comose.yaml

version: "3"
services:
  web:
    build:
      context: .
      dockerfile: ./Dockerfile
    env_file: .env

.env

TEST=hoge

.env2

TEST=hoge2

結果

$go run main.go
panic
$TEST=hoge go run main.go 
hello world
hoge
$docker build . -t test
$docker run test
panic
$docker run --env-file .env test
hello world
hoge
$docker run --env-file .env2 test
hello world
hoge2
$docker-compose up
web_1  | hello world
web_1  | hoge

ESLintで複数ファイル、複数フォルダをターゲットにする

結論

$eslint test1.js "testdir/**/*.ts" "testdir2/**/*.@(js|ts)" --parser-options=xxxx

バージョン

"eslint": "^6.8.0"

ドキュメント

https://eslint.org/docs/user-guide/command-line-interface

eslint file1.js file2.js

docker-composeで実行環境の変数をコンテナに展開する方法

結論

https://docs.docker.com/compose/environment-variables/#pass-environment-variables-to-containers

docker-compse.yamlのenvironmentに、実行環境の環境変数と同じキーをバリューなしで書く

環境

$docker --version
Docker version 19.03.8, build afacb8b

検証

1. Dockerfile, docker-compose.yamlを書く

Dockerfile

FROM node:alpine
ENV TEST_ENV $TEST_ENV
RUN printenv

docker-compose.yaml

version: "3"
services:
  test:
    build: .
    environment:
      - TEST_ENV
    tty: yes

2. 実行環境に環境変数を登録

$export TEST_ENV=test_env
$echo $TEST_ENV
test_env

3. コマンド実行

$docker-compose build
$docker-compose up -d
$docker-compose exec test ash -c "printenv"
...
TEST_ENV=test_env
...