【React.js】makeStylesのスタイル指定方法

f:id:tm200:20211207233515p:plain

React.js(Next.js)で実装する際にmakeStylesの利用方法を調べたので、忘れないようにメモ。
気になるものがあったら、順次追記していきます。


coin-look.pages.dev


first-child

特に迷うことは無い。

const useStyles = makeStyles({
  root: {
    '& div:first-child': {
       ....
    },
});

last-child

first-childと同様。

const useStyles = makeStyles({
  root: {
    '& div:last-child': {
       ....
    },
});

nth-child

スタイルを指定したい要素の中に&:nth-child(n)という形式で定義する。

const useStyles = makeStyles({
  root: {
    '&:nth-child(2)': {
       ....
    },
});

not

&:not(:~)という形で指定可能。  

const useStyles = makeStyles({
  root: {
    '&:not(:nth-child(2))': {
       ....
    },
});

メディアクエリ

@media (min-width:1280px)のような形で指定可能。  

const useStyles = makeStyles({
  root: {
    display: 'flex',
    '@media (max-width:1024px)': {
      display: 'block',
      ....
    },
});

【HiveQL】pyhiveとPrestoでテーブル操作

f:id:tm200:20210704143739p:plain

beelineで実行していたクエリをpyhive + Prestoで再実装した際に書き方が違う部分があった為、備忘メモ。  


coin-look.pages.dev


 LOCATIONを指定してテーブル作成

元のクエリはこちら。

CREATE EXTERNAL TABLE <テーブル名> (<カラム名> <型>, ...) ROW FORMAT DELIMITED FIELDS TERMINATED BY <区切文字、eg. '\t'> LOCATION <HDFSのパス>

pyhive + Prestoで書くと以下のようになる。

cursor = presto.connect(...).cursor()
query = "CREATE TABLE test_table (id integer, note varchar) WITH (format='TEXTFILE', textfile_field_separator='\t', external_location='/path/to/hdfs')"
cursor.execute(query)

# fetchしないとテーブル作成後の処理が上手くいかない、エラーログも見れる
print(cursor.fetchone())

cursor.execute('desc test_table')
print(cursor.fetchone())

INSERT OVERWRITE

元のクエリ。

INSERT OVERWRITE <テーブル名> SELECT sum_a, b FROM (
  SELECT SUM(a) AS sum_a, b FROM (
    SELECT a, b FROM table1 UNION ALL
    SELECT a, b FROM table2 UNION ALL
    SELECT a, b FROM table3
  ) t1 GROUP BY b
) t2 WHERE sum_a > {hivevar:a_param}

PrestoINSERT OVERWRITEは使用できません。
drop後にINSERT INTOで作成する必要があります。

docs.treasuredata.com

cursor = presto.connect(...).cursor()

# drop
cursor.execute('DROP TABLE IF EXISTS test_table')

query = 'INSERT INTO test_table (sum_a, b) WITH tmp_tb AS (
  SELECT SUM(a) AS sum_a, b FROM (
    SELECT a, b FROM table1 UNION ALL
    SELECT a, b FROM table2 UNION ALL
    SELECT a, b FROM table3
  ) GROUP BY b)
  SELECT sum_a, b FROM tmp_tb WHERE  sum_a > %s'

cursor.execute(query, (100,))
print(cursor.fetchall())

【Node.js】npmパッケージの脆弱性対応

f:id:tm200:20210930200410p:plain

CIで脆弱性チェックがエラーとなり、npm audit以外の方法で応急処置をしたのでメモ。  
修正後は要動作確認。  


coin-look.pages.dev


 npm audit

まずは npm audit 等で検出されたパッケージのレポジトリを調べ、必要であれば package.json のバージョンを修正後にnpm audit fixを実行。
node_modules や package-lock.jsonは削除した方が間違いが無さそう。

$ npm audit fix

npm-force-resolutions

github.com

npm audit fixで解決しなかった場合に、どうにかして脆弱性のあるライブラリのバージョンを修正したい場合にnpm-force-resolutionsが使用できます。
package.jsonのscripts.preinstallにnpx npm-force-resolutionsresolutionsにバージョンを修正したいパッケージ情報を記載します。
依存関係を無理やり変更させる為、使用する場合はバージョンアップ後の動作確認を良く行ってください。

{
  "name": "xxxxx",
  "version": "0.0.1",
  "description": "",
  "scripts": {
    "preinstall": "npx npm-force-resolutions",     # ここ
    "build": "..."
  },
  "dependencies": {
    "vue": "^2.6.14",
    ...
  },
  "dev-dependencies": {
    "vue-jest": "^4.0.1",
    ...
  },
  "resolutions": {
     "ansi-regex": "5.0.1"     # ここ
  }
}

Dockerfileからbuildする際にエラーとなった為、.npmrcにunsafe-perm=trueを追記して解決しました。
unsafe-perm=trueで、パッケージスクリプト(preinstall)の実行時のUID/GID切り替えを抑制します。

# .npmrc
registry=https://xxx.xxx.xxx/...
unsafe-perm=true     # ここ

【Python】urllibでプロキシ設定

f:id:tm200:20210915184401p:plain

urllibで社内のプロキシサーバーを経由して外部接続という処理を実装しました。
外部接続先のAPIBasic認証が必要で、少し詰まったのでメモ。
requestsモジュールだと、プロキシ設定 + 接続先でBasic認証が上手く動かなかった為、urllibモジュールを使用しています。
上手いやり方などあれば、教えてください😊

実装

import os
import base64
import json
import urllib.request


def exec_proxy_request(usename: str, passwd: str, token: str):

    user_pass = f'{usename}:{passwd}'
    header = {
        # アクセス先のBasic認証
        'Authorization': f"Basic {base64.b64encode(user_pass.encode('utf-8')).decode('utf-8')}"
        # プロキシサーバの認証情報、必要に応じて
        'Proxy-Authorization': f'Bearer {token}'
    }

    req = urllib.request.Request('<アクセス先URL>', headers=header, method='GET')
    # プロキシの設定
    req.set_proxy('xxx.proxy.jp', 'http')
    req.set_proxy('xxx.proxy.jp', 'https')

    with urllib.request.urlopen(req) as res:
        status_code = res.getcode()
        res_body = res.read().decode('utf-8')

        if not status_code == 200:
            raise Exception(res_body)

        json_data = json.loads(res_body)

    return json_data

【Kubernetes】IngressのURL Rewrite設定

Ingressのpath設定でリクエストを振り分ける際にURLのrewriteを行ったのでメモ。
設定がコントローラーにより異なるようです。

kubernetes-ingress

annotationsnginx.ingress.kubernetes.io/rewrite-targetを設定すると良いようです。
rewrite-targetに/を指定する事により、/v2アクセス時にservice2/(インデックスルート)にアクセスします。

kubernetes.io

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test
  namespace: test-namespace
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /v2
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 80
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 80
  • Git Hub

github.com

Nginx Ingress Controller

kubernetes-ingressと同様にnginx.ingress.kubernetes.io/rewrite-targetで指定できるようです。

kubernetes.github.io

  • Git Hub

github.com

nghttpx Ingress Controller

zlab社製のnghttpxingress.zlab.co.jp/path-configにpathのrewrite処理を記載する必要があります。
詳細はドキュメントが参考になります。

nghttp2.org

以下の設定では、example.co.jp/v2/アクセス時にservice2/にルーティングされます。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test
  namespace: test-namespace
  annotations:
    ingress.zlab.co.jp/path-config: |
      example.co.jp/v2/:
        mruby: |
          class App
            def on_req(env)
              # `/v2`を削除している
              env.req.path = env.req.path.sub(/^\/[^\/]+/, '')
            end
          end
          App.new

spec:
  rules:
  - http:
      paths:
      # `/v2`も入れないと`example.co.jp/v2`(最後の`/`無し)がNot Foundとなります
      - path: /v2
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 80
      - path: /v2/
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 80
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 80
  • Git Hub

github.com

Traefik Controller (Rancher, k3s)

k3s環境ではIngressControllerにTraefieがデフォルトで適用されます。
今までのIngressControllerと異なり、MIddlewareというCRDのデプロイが別途必要になります。

doc.traefik.io

以下、/v2アクセス時にservice2/(インデックスルート)にアクセスする例となります。

apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: replacepathregex-service2
  namespace: test-namespace
spec:
  replacePathRegex:
    regex: ^/v2/(.*)
    replacement: /$1

annotationstraefik.ingress.kubernetes.io/router.middlewaresを指定します。
設定する値は${namespace名}-${Middleware名}@kubernetescrdという形式にする必要があります。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test
  namespace: test-namespace
  annotations:
    traefik.ingress.kubernetes.io/router.middlewares: test-namespace-replacepathregex-service2@kubernetescrd
spec:
  ingressClassName: traefik
  rules:
  - http:
      paths:
      - path: /v2
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 80
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 80

【Python】smtplibでメール送信

f:id:tm200:20210829222902j:plain

Pythonでメール通知の実装メモ。
ホスト名などは適宜変更してください。

実装

ライブラリは不要です。

# -*- coding: utf-8 -*-
import getpass
import platform
import smtplib
from datetime import datetime
from email.mime.text import MIMEText
from email.utils import formatdate


def send_mail(to: str, mail_text: str):
    """
    メール送信
    :param to: 送信先
    :param mail_text: 本文
    """
    now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    host_name = platform.uname()[1]

    message = MIMEText(mail_text)
    message['Subject'] = f'[{now}][{host_name}]'
    message['From'] = f'{getpass.getuser()}@{host_name}'
    message['To'] = to
    message['Date'] = formatdate()
    with smtplib.SMTP('localhost') as smtp:
        smtp.send_message(message)

【Kubernetes】kubectl の便利コマンド

f:id:tm200:20210826215705p:plain

使わなくなると忘れそうなので、kubectlコマンドをメモ。
alias k=kubectl 実行済の想定です。
随時、追加します。

入門ならこの一冊😊

トークン取得

$ (k describe secret $(k get secrets | grep <サービスアカウント名> | cut -f1 -d ' ') | grep -E '^token' | cut -f2 -d':' | tr -d '\t')

ネームスペース切り替え

$ k config set-context $(k config current-context) --namespace=<ネームスペース>

# namespace一覧
$ k config view | grep namespace

tls用secret作成

base64デコード時のオプションを--decodeとすると、macでも動きます。

$ k create secret tls <secret名> --key=xxx.key --cert=xxx.crt

# 確認コマンド
$ k get secret/<secret名> -o yaml

# jqが使える場合、項目指定も
$ k get secret/<secret名> -o json | jq -r '.data."<項目名>" | base64 --decode'

# historyに出力させたくない場合
$ k get secret/<secret名> -o yaml > secret.yaml
$ grep "^data:" -A <secretの件数> secret.yaml | awk -F '{print $2}' | base64 --decode

リソースを更新して再起動

# コンフィグマップの編集
$ k edit cm <ConfigMap名>

# 変更を反映させる為、再起動
$ k rollout restart <deployment名>

ポートフォワードでデバッグ

以下のコマンドで対象Podの80番ポートがlocalhost:8080でアクセス可能となる。

$ k port-forward <pod名> 8080:80