これは、なにをしたくて書いたもの?
TerraformのProviderを見ていると、Sonatype Nexus用のProviderがあったのでちょっと試してみたいなと。
Nexus Provider
Sonatype NexusのTerraform Providerです。
リポジトリーの定義などをスクリプトなどでできるといいなと思っていたのですが、REST APIかGroovyスクリプトしか方法を
知りませんでした。
Terraformで定義できるのなら、宣言的に書けて良さそうですね、ということで。
環境
今回の環境は、こちら。
$ terraform version Terraform v1.4.6 on linux_amd64
Sonatype Nexusは、Dockerイメージを使うことにします。
起動。
$ docker container run -it --rm --name nexus3 sonatype/nexus3:3.53.0
Nexusコンテナにアクセスする際のIPアドレスは、172.17.0.2とします。
Sonatype NexusのMavenリポジトリーをTerraformで定義する
では、Sonatype NexusのMavenリポジトリーをNexus Providerを使って、Terraformで定義してみましょう。
今回はHostedリポジトリー、Proxyリポジトリー、そしてその2つを含んだGroupリポジトリーを作成してみます。
- Resource nexus_repository_maven_hosted
- Resource nexus_repository_maven_proxy
- Resource nexus_repository_maven_group
結果はこちら。
main.tf
terraform { required_version = "v1.4.6" required_providers { nexus = { source = "datadrivers/nexus" version = "1.21.2" } } } provider "nexus" { username = "admin" # 初期パスワードは /nexus-data/admin.password に記載 password = "admin123" url = "http://172.17.0.2:8081" insecure = true } resource "nexus_repository_maven_hosted" "my_maven_hosted_repo" { name = "my-maven-hosted-repo" online = true maven { layout_policy = "STRICT" version_policy = "MIXED" content_disposition = "INLINE" } storage { blob_store_name = "default" strict_content_type_validation = true write_policy = "ALLOW" } } resource "nexus_repository_maven_proxy" "my_maven_proxy_repo" { name = "my-maven-proxy-repo" online = true proxy { remote_url = "https://repo1.maven.org/maven2/" } maven { layout_policy = "STRICT" version_policy = "RELEASE" content_disposition = "INLINE" } storage { blob_store_name = "default" strict_content_type_validation = true } http_client { auto_block = true blocked = false } negative_cache { enabled = true ttl = 1440 } } resource "nexus_repository_maven_group" "my_maven_group_repo" { name = "my-maven-group-repo" online = true group { member_names = [ nexus_repository_maven_hosted.my_maven_hosted_repo.name, nexus_repository_maven_proxy.my_maven_proxy_repo.name ] } storage { blob_store_name = "default" strict_content_type_validation = true } }
provider
にSonatype Nexusへの接続情報を定義。
provider "nexus" { username = "admin" # 初期パスワードは /nexus-data/admin.password に記載 password = "admin123" url = "http://172.17.0.2:8081" insecure = true }
あとは、ドキュメントを見つつリポジトリーを定義。上から、Hostedリポジトリー、Proxyリポジトリー、Groupリポジトリーです。
resource "nexus_repository_maven_hosted" "my_maven_hosted_repo" { name = "my-maven-hosted-repo" online = true ## 省略 } resource "nexus_repository_maven_proxy" "my_maven_proxy_repo" { name = "my-maven-proxy-repo" online = true ## 省略 } resource "nexus_repository_maven_group" "my_maven_group_repo" { name = "my-maven-group-repo" online = true ## 省略 }
設定値が不安な時は、Sonatype NexusのWeb UIでリポジトリーを作成する時の情報を見ると良いかもですね。
terraform init
して
$ terraform init
apply
。
$ terraform apply
リポジトリーが作成できました。
REST APIで確認する場合は、こちら。
$ curl 172.17.0.2:8081/service/rest/v1/repositories
デプロイしてみる
作成したMavenリポジトリーに、アーティファクトをデプロイして動作確認してみましょう。
サンプルを作成。
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.littlewings</groupId> <artifactId>sample-app</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> <repositories> <repository> <id>my-maven-group-repo</id> <name>My Maven Group Repository</name> <url>http://172.17.0.2:8081/repository/my-maven-group-repo/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>my-maven-group-repo</id> <name>My Maven Group Repository</name> <url>http://172.17.0.2:8081/repository/my-maven-group-repo/</url> </pluginRepository> </pluginRepositories> <distributionManagement> <repository> <id>my-maven-hosted-repo</id> <name>My Maven Hosted Repository</name> <url>http://172.17.0.2:8081/repository/my-maven-hosted-repo/</url> </repository> </distributionManagement> </project>
src/main/java/org/littlewings/sample/Greeting.java
package org.littlewings.sample; public class Greeting { public String hello(String message) { return String.format("Hello %s!!", message); } }
settings.xml
<?xml version="1.0" encoding="UTF-8"?> <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd"> <servers> <server> <id>my-maven-hosted-repo</id> <username>admin</username> <password>admin123</password> </server> </servers> </settings>
デプロイ。
$ mvn package deploy -s settings.xml
確認。
OKですね。
ハマったこと
最初、必須項目だけ定義していたらProxyリポジトリーの作成でハマりました。
Providerがクラッシュするんですよね…。
nexus_repository_maven_proxy.my_maven_proxy_repo: Creating... ╷ │ Error: Plugin did not respond │ │ with nexus_repository_maven_proxy.my_maven_proxy_repo, │ on main.tf line 37, in resource "nexus_repository_maven_proxy" "my_maven_proxy_repo": │ 37: resource "nexus_repository_maven_proxy" "my_maven_proxy_repo" { │ │ The plugin encountered an error, and failed to respond to the plugin.(*GRPCProvider).ApplyResourceChange call. The plugin logs may contain more details. ╵ Stack trace from the terraform-provider-nexus_v1.21.2 plugin: panic: runtime error: index out of range [0] with length 0 goroutine 40 [running]: github.com/datadrivers/terraform-provider-nexus/internal/services/repository.getMavenProxyRepositoryFromResourceData(0xde39e0?) github.com/datadrivers/terraform-provider-nexus/internal/services/repository/resource_repository_maven_proxy.go:45 +0xffe github.com/datadrivers/terraform-provider-nexus/internal/services/repository.resourceMavenProxyRepositoryCreate(0x0?, {0xb7b2e0?, 0xc0003e3140}) github.com/datadrivers/terraform-provider-nexus/internal/services/repository/resource_repository_maven_proxy.go:168 +0x66 github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*Resource).create(0xde39e0?, {0xde39e0?, 0xc0003ce330?}, 0xd?, {0xb7b2e0?, 0xc0003e3140?}) github.com/hashicorp/terraform-plugin-sdk/v2@v2.24.0/helper/schema/resource.go:695 +0x178 github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*Resource).Apply(0xc000436620, {0xde39e0, 0xc0003ce330}, 0xc0002a5a00, 0xc0003e1800, {0xb7b2e0, 0xc0003e3140}) github.com/hashicorp/terraform-plugin-sdk/v2@v2.24.0/helper/schema/resource.go:837 +0xa7a github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*GRPCProviderServer).ApplyResourceChange(0xc0003051e8, {0xde39e0?, 0xc0003ce210?}, 0xc0004669b0) github.com/hashicorp/terraform-plugin-sdk/v2@v2.24.0/helper/schema/grpc_provider.go:1021 +0xe3c github.com/hashicorp/terraform-plugin-go/tfprotov5/tf5server.(*server).ApplyResourceChange(0xc000366460, {0xde39e0?, 0xc0002f79e0?}, 0xc0003dc380) github.com/hashicorp/terraform-plugin-go@v0.14.0/tfprotov5/tf5server/server.go:818 +0x574 github.com/hashicorp/terraform-plugin-go/tfprotov5/internal/tfplugin5._Provider_ApplyResourceChange_Handler({0xc840a0?, 0xc000366460}, {0xde39e0, 0xc0002f79e0}, 0xc0003dc310, 0x0) github.com/hashicorp/terraform-plugin-go@v0.14.0/tfprotov5/internal/tfplugin5/tfplugin5_grpc.pb.go:385 +0x170 google.golang.org/grpc.(*Server).processUnaryRPC(0xc0003f2000, {0xde6540, 0xc00048a1a0}, 0xc000354ea0, 0xc000432de0, 0x129b980, 0x0) google.golang.org/grpc@v1.50.1/server.go:1340 +0xd13 google.golang.org/grpc.(*Server).handleStream(0xc0003f2000, {0xde6540, 0xc00048a1a0}, 0xc000354ea0, 0x0) google.golang.org/grpc@v1.50.1/server.go:1713 +0xa1b google.golang.org/grpc.(*Server).serveStreams.func1.2() google.golang.org/grpc@v1.50.1/server.go:965 +0x98 created by google.golang.org/grpc.(*Server).serveStreams.func1 google.golang.org/grpc@v1.50.1/server.go:963 +0x28a Error: The terraform-provider-nexus_v1.21.2 plugin crashed!
スタックトレースからソースコードを見ると、negative_cache
は設定上はオプションで、実際には必須なようなのでこちらを加えると
動作しました。
まとめ
Nexus Providerを使って、Sonatype NexusをTerraformで操作してみました。
若干ハマるところがありましたが、REST APIで頑張るよりはTerraformで扱えた方が個人的にはわかりやすいですね。
使えるところでは、使っていきましょう。