Skip to main content

Posts

Showing posts from September, 2020

OpenAPI Generator 4.3.1でJava向けGeneratorとmicroprofileの組み合わせによって生成されるライセンスの問題

OpenAPIでJavaのクライアントサイドのコードを生成しようとした。 いくつか試すと、色々とすごい数のファイルを作るものが多い中、microprofileは比較的少なめで良さそうに見えた。 というわけで生成して、importに何が足りないか確認していた。 と、生成されたコードの上部にApache Licenseの表記が。 仕事でしている以上、これはOSSではないので、Apache Licenseとか勝手につけられるのは正直困る。トラブルにはなりにくいライセンスであるとはいえ。 もしかしてこれまでも気がつかずに......?と思い過去の typescript-angularやjax-rs+quarkusでの生成コードもみたが、そちらはライセンスの追加はなかった。 仕方がないのでjava + microprofileでの生成をやめて、java + resteasyで仕事としては進めることにした。 ちなみに、生成は次のような方法で実現した。 (普通はビルドプロセスに組み込むのだけど、動作確認中なのでcompileJava.dependsOn tasks.openApiGenerateのように組み込むことはしなかった) build.gradle(一部): task testSpecOpenApiGenerate (type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask) { generatorName = 'java' configFile = "${rootDir}/src/main/resources/external/openapi-config.json" inputSpec = "${rootDir}/src/main/resources/external/petstore.yaml" outputDir = "${rootDir}/src/gen" } openapi-config.json: { "apiPackage" : "xxxx.xxxx.xxxx.external.infrastructure.xxxx.resources&qu

Pythonで作ったCLIアプリの配布

Pythonで書いたプログラムをエンドユーザーに配布することになった。 カウンターパートの希望で、PyPIのようなpip経由でインストール可能な形式と、圧縮ファイル形式の2種が必要となった。 前者はプライベートネットワーク内のArtifactoryの中に構築してあるPyPIのレジストリへ、後者はそこへアクセスできない人へ。 検索してみるとsetup.pyを使用した配布が多い。とりあえず今回は巷にあるPythonのパッケージをExecutableなファイルにするツールは使わずこの正攻法を使用する。 そもそも開発環境ではpipenvを使用していて、依存性管理もそれで実施している。 が、pipenvでの実現方法が残念ながらストレートに理解できそうな方法では見当たらなかったので、Pipfileとsetup.pyで依存性をそれぞれ書きながらの対処となる。 まず、pipenv向けに作っていた修正前のsetup.py。 from setuptools import setup setup() これを例えば次のようにする。(値の一部はサニタイズのため適当) from setuptools import setup, find_packages setup( name= 'mypycli' ,     version= '1.0.0' ,     packages=find_packages(include=[ "config*" ,  "src*" ]),     scripts=[ "src/mypycli.py" ],     entry_points={          "setuptools.installation" : [              "eggsecutable = src.mypycli:main" ,         ]     },     include_package_data= True ,     description= '' ,     install_requires=[          'tqdm' ,     ],     url= 'https

structoptで踏み出すRustのCLIの第一歩

要所でRustが使われるシーンも多くなってきているように感じて、Rustのスキル向上の圧を自分の内側からも感じてる。 わかりやすいところから入ってわかった気になるのが好きなので、まずはCLIとしてどうできるのか、みたいなところを取っ掛かりにする。 つい先月のOreillyのニュースレターで次の記事とリポジトリが紹介されていた。 Go vs Rust: Writing a CLI tool - cuchi.me Hi there! this page is where I share my thoughs and knowledge cuchi.me cuchi/hashtrack A simple Twitter hashtag tracking service. Contribute to cuch github.com 内容としては、GoとRust、どっちが本当に早いのか、ということで、機能的には同じことをする処理を2言語で書き分けて比較するという内容だった。 (Rustの方が早いことが多かったものの、ビルドはGoの方が早いという結果だったと記憶してる) Rustを不必要にWeb APIのサーバーとして使うケースは趣味の範疇で見かけることも多いのだけど、ライブラリ群の成長の仕方を見てもまだまだMatureではないと思えるし、そうともすれば、組織として一定のRustへのこだわりがない限り採択はしないだろうから、もし仕事に使えることを念頭に置くならCLIの側面での使いっぷりを見ていく方が現実線だと個人的には思っている。 というわけで、そのCLIの方面での優れた例だと思ったので、サブコマンドの設定とヘルプの表示までを見てみた。 ソースコードはGitHubにある。 Rustは1.46で試した。 tkhm/sandbox-rust Contribute to tkhm/sandbox-rust development by creating an ac github.com $ ./target/debug/rust-cli-play --help rust-cli-play 0.1 .0 rust-cli-play COMMAND [OPTIONS, ...] USAGE: rust-cli-play <SUBCOMMAND> FLAGS: -

マイクロサービスのアーキテクチャー研修メモ

マイクロサービスのアーキテクチャーに関する研修を受講したので、ただの箇条書きだがメモとして残しておく。 * SOAとMSAは考えとしては近しい。 * ただし、SOAでは思想として、中央集権的な部分がある。 * サービスとして切り出すところまでは同じだとしても、そのサービスやデータ管理においては最終的に統合することが前提になっている。 * マイクロサービスの適切な単位・粒度、というのはまだ確立されていない。 * マイクロサービスとAPIは関係性としては、マイクロサービス>API。マイクロサービス単位にAPIが1単位になっているわけではないが、少なくともAPIはマイクロサービスの範囲内の物事を扱うもので、そのI/Fとしての表現。 * サービスやAPIを識別するアプローチとしては、ユースケースからAPIの識別を、ドメイン分析からサービスの識別を、データモデル分析からデータのマッピングをする、といった関係性のイメージ。 この話は結構聞いていると考えがクリアになってきて、また、一口にこれが最適と言える単位・粒度が確立されていないというのも、巷でなかなか明確な回答を探しても見つからないことの裏打ちになって、自分なりの考えを確立するための努力をしても良いなあと思えるだけの機会にはなった。 マイクロサービスの話の文脈ではドメイン駆動設計の話もよく出てくる。 『実践ドメイン駆動設計』も近頃どうにか読み終えたばかりなので、最後の方に載っている所謂軽量DDDを成すような技術的な設計パターンが自分にはやはりわかりがいいなあと思いながら、ドメイン設計の話も徐々に読み解している。 ドメイン分析では次のように触れられていたので、チーミングの時や、モデリング活動の時には忘れないようにしたい。 よくあるのが、そのドメインについての経験がない「ドメインエキスパート」が複数集まったときに、単なるビジネスアナリストとして動いてしまうということだ。 出典:実践ドメイン駆動設計 P.8   業務のエキスパートのメンタルモデルを反映したソフトウェアを開発する。これは決して、「現実世界」をそのままモデリングするということではない。DDD では、現状をそのままモデリングするのではなく、業務により役立つモデルを作る。 出典:実践ドメイン駆動設計 P.9

Pythonでsubparserを使ってCLIアプリを洗練させる

  何らかプログラムを書くとき、自分の場合は最近はWeb APIかあるいはバッチ処理のものが多い。 バッチ処理について言うと、メンテナンスできる可能性のある人が多いということやライブラリの充実度合いからPythonが選ばれる。 PythonでCLIを書くときに近頃調べて知ったサブコマンドというものがあり、それを使うと、多少なりともGitのCLIのような、このコマンドでは何ができるのか、が明示しやすくなるのでメモを残す。 まず、自分が普段一緒に仕事をしているチームでは、tqdmとargparseは定番だった。 argparse — Parser for command-line options, arguments and sub-commands — Python 3.7.9 documentation docs.python.org tqdm documentation A Fast, Extensible Progress Meter tqdm.github.io Argparseは、CLIをCLIたらしめる、引数の受付けやRequired/Optionalの指定、各引数の説明を実現してくれるライブラリ。(しかも標準提供......!) tqdmは、長く時間がかかる処理などを前提に、進み具合をプログレスバーのようなかたちで出してくれるので、処理中の時などにユーザーに情報提供するためには入れておきたいライブラリ。 で、しばらくそれらを使いながら過ごしていた結果感じた課題として、コマンドが複数に成長を始め、コマンドによって必要なオプションの種類が大きく分岐してきていたということ。 唐突だけど例えば、自販機の在庫状況を調べられるCLIを作っているとして、次のような3つのコマンドを用意しているとする。 1. 自販機全体の在庫を知る -c コマンド名 -i 自販機のID 2. 自販機のある商品の在庫を知る -c コマンド名 -i 自販機のID -p 商品のID 3. 全体として取り扱っているある商品の詳細を知る -c コマンド名 -p 商品のID これを何の工夫もなく実現すると、1と2では必須の自販機のIDは3では不要で、必須と任意や不要なものが混ざる。 そうすると、すべての引数を任意で受け付けた上で、個別のコマンドの分岐内でオプションについて処理する必要が出てくる。 L

解決:自作ライブラリ使用時のCratesでのエラー on Jenkins

前回の続き。 自作ライブラリ使用時のCratesでのエラー on Jenkins 仕事でRustを使うにあたり、crates.ioには公開しない方法で自作のライブラリを使用しようとしている。 少し整理して blog.tkhm.dev 色々と調べたが結論としては、事前にCredentialsをコンテナの中に仕込むより他にはなさそう。 正確には、次の2つが考えられた。 * 依存プライベートライブラリの指定をgitではなくpathに置き換えて、git submoduleで管理する * 事前にCredentialsを入れたコンテナを作りビルドなどに使う ただ、前者はライブラリに依存する対象が増えるほど面倒になり、またJenkinsfile上では、事前に git ステップによりdirで指定したpath先にcloneしないといけないので、正直言って小手先の対応というか、数が増えていくに従って面倒と感じるような類だった。 というわけで事前にCredentialsを封入。Dockerfileの記述としてはこんな感じにしてみた。 環境変数にexportしたユーザー名とアクセストークンを取り込む方法にすることで、今後の更新を楽にしている。 Dockerfile FROM rust: 1.44 AS build WORKDIR /usr/src RUN rustup target add x86_64-unknown-linux-gnu RUN rustup component add clippy RUN rustup component add rustfmt ARG GITHUB_USERNAME ARG GITHUB_TOKEN COPY git-credential-github-token RUN git config --system credential.helper store && sh git-credential-github-token | git credential approve ただ、注意が必要なのは、この方法ので作ったコンテナのレイヤーにはこのユーザー名とパスワードが明記されてしまっていると言うこと。 言い換えれば、このコンテナを入手できれば対象の環境で誰でも簡単に、Personal Access Tokenの権限の範囲で好きな