pulumi-component
再利用可能なインフラコンポーネントの作成、コンポーネントインターフェースの設計、多言語サポートのセットアップ、またはコンポーネントパッケージの配布を行う際に活用できる、Pulumi の ComponentResource クラスを記述するためのガイドです。
description の原文を見る
Guide for authoring Pulumi ComponentResource classes. Use when creating reusable infrastructure components, designing component interfaces, setting up multi-language support, or distributing component packages.
SKILL.md 本文
Pulumi コンポーネントの作成
ComponentResource は関連するインフラストラクチャリソースを再利用可能な論理単位にグループ化します。コンポーネントはインフラストラクチャを理解しやすく、再利用でき、保守しやすくします。コンポーネントは pulumi preview/pulumi up 出力と Pulumi Cloud コンソールで、ネストされた子リソースを持つ単一ノードとして表示されます。
このスキルはコンポーネント作成のライフサイクル全体をカバーしています。一般的な Pulumi のコーディングパターン (Output の処理、シークレット、エイリアス、プレビューワークフロー) については、pulumi-best-practices スキルを使用してください。
このスキルを使用する場合
以下の場合にこのスキルを呼び出してください:
- 新しい ComponentResource クラスを作成する場合
- コンポーネントの args インターフェースを設計する場合
- コンポーネントを複数の Pulumi 言語から使用可能にする場合
- コンポーネントパッケージを公開または配布する場合
- インラインリソースを再利用可能なコンポーネントにリファクタリングする場合
- コンポーネントの動作をデバッグする場合 (出力がない、作成が止まっている、子リソースがレベルを間違っている)
コンポーネントの構成
すべてのコンポーネントには4つの必須要素があります:
- ComponentResource を拡張し、type URN で
super()を呼び出す - 標準パラメータを受け入れる: name、args、および
ComponentResourceOptions - すべての子リソースに
parent: thisを設定する - コンストラクタの最後で
registerOutputs()を呼び出す
TypeScript
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
interface StaticSiteArgs {
indexDocument?: pulumi.Input<string>;
errorDocument?: pulumi.Input<string>;
}
class StaticSite extends pulumi.ComponentResource {
public readonly bucketName: pulumi.Output<string>;
public readonly websiteUrl: pulumi.Output<string>;
constructor(name: string, args: StaticSiteArgs, opts?: pulumi.ComponentResourceOptions) {
// 1. Call super with type URN: <package>:<module>:<type>
super("myorg:index:StaticSite", name, {}, opts);
// 2. Create child resources with parent: this
const bucket = new aws.s3.Bucket(`${name}-bucket`, {}, { parent: this });
const website = new aws.s3.BucketWebsiteConfigurationV2(`${name}-website`, {
bucket: bucket.id,
indexDocument: { suffix: args.indexDocument ?? "index.html" },
errorDocument: { key: args.errorDocument ?? "error.html" },
}, { parent: this });
// 3. Expose outputs as class properties
this.bucketName = bucket.id;
this.websiteUrl = website.websiteEndpoint;
// 4. Register outputs -- always the last line
this.registerOutputs({
bucketName: this.bucketName,
websiteUrl: this.websiteUrl,
});
}
}
// Usage
const site = new StaticSite("marketing", {
indexDocument: "index.html",
});
export const url = site.websiteUrl;
Python
import pulumi
import pulumi_aws as aws
class StaticSiteArgs:
def __init__(self,
index_document: pulumi.Input[str] = "index.html",
error_document: pulumi.Input[str] = "error.html"):
self.index_document = index_document
self.error_document = error_document
class StaticSite(pulumi.ComponentResource):
bucket_name: pulumi.Output[str]
website_url: pulumi.Output[str]
def __init__(self, name: str, args: StaticSiteArgs,
opts: pulumi.ResourceOptions = None):
super().__init__("myorg:index:StaticSite", name, None, opts)
bucket = aws.s3.Bucket(f"{name}-bucket",
opts=pulumi.ResourceOptions(parent=self))
website = aws.s3.BucketWebsiteConfigurationV2(f"{name}-website",
bucket=bucket.id,
index_document=aws.s3.BucketWebsiteConfigurationV2IndexDocumentArgs(
suffix=args.index_document,
),
error_document=aws.s3.BucketWebsiteConfigurationV2ErrorDocumentArgs(
key=args.error_document,
),
opts=pulumi.ResourceOptions(parent=self))
self.bucket_name = bucket.id
self.website_url = website.website_endpoint
self.register_outputs({
"bucket_name": self.bucket_name,
"website_url": self.website_url,
})
site = StaticSite("marketing", StaticSiteArgs())
pulumi.export("url", site.website_url)
Type URN フォーマット
super() の第1引数は type URN です: <package>:<module>:<type>。
| セグメント | 慣例 | 例 |
|---|---|---|
| package | 組織またはパッケージ名 | myorg、acme、pkg |
| module | 通常は index | index |
| type | PascalCase のクラス名 | StaticSite、VpcNetwork |
完全な例: myorg:index:StaticSite、acme:index:KubernetesCluster
registerOutputs は必須
理由: registerOutputs() がないと、コンポーネントは Pulumi コンソールで「作成中」の状態で止まり、出力がステートに保存されません。
間違い:
class MyComponent extends pulumi.ComponentResource {
public readonly url: pulumi.Output<string>;
constructor(name: string, args: MyArgs, opts?: pulumi.ComponentResourceOptions) {
super("myorg:index:MyComponent", name, {}, opts);
const bucket = new aws.s3.Bucket(`${name}-bucket`, {}, { parent: this });
this.url = bucket.bucketRegionalDomainName;
// registerOutputs がない -- コンポーネントが「作成中」で止まる
}
}
正しい:
class MyComponent extends pulumi.ComponentResource {
public readonly url: pulumi.Output<string>;
constructor(name: string, args: MyArgs, opts?: pulumi.ComponentResourceOptions) {
super("myorg:index:MyComponent", name, {}, opts);
const bucket = new aws.s3.Bucket(`${name}-bucket`, {}, { parent: this });
this.url = bucket.bucketRegionalDomainName;
this.registerOutputs({ url: this.url });
}
}
子リソース名をコンポーネント名から派生させる
理由: ハードコードされた子リソース名は、コンポーネントが複数回インスタンス化されると衝突します。
間違い:
// このコンポーネントの2つのインスタンスが存在すると衝突する
const bucket = new aws.s3.Bucket("my-bucket", {}, { parent: this });
正しい:
// コンポーネントインスタンスごとにユニーク
const bucket = new aws.s3.Bucket(`${name}-bucket`, {}, { parent: this });
Args インターフェースの設計
args インターフェースは最も影響力のある設計上の決定です。コンシューマーが何を設定でき、コンポーネントがどの程度再利用可能かを定義します。
プロパティを Input<T> でラップする
理由: Input<T> はプレーン値と他のリソースからの Output<T> の両方を受け入れます。これがないと、コンシューマーは .apply() で出力をアンラップする必要があります。
間違い:
interface WebServiceArgs {
port: number; // コンシューマーが Outputs をアンラップする必要がある
vpcId: string; // vpc.id を直接受け入れられない
}
正しい:
interface WebServiceArgs {
port: pulumi.Input<number>; // 8080 または someOutput を受け入れる
vpcId: pulumi.Input<string>; // "vpc-123" または vpc.id を受け入れる
}
構造をフラットに保つ
深くネストされた arg オブジェクトを避けます。フラットなインターフェースはより使いやすく、進化しやすいです。
// フラットなものが好ましい
interface DatabaseArgs {
instanceClass: pulumi.Input<string>;
storageGb: pulumi.Input<number>;
enableBackups?: pulumi.Input<boolean>;
backupRetentionDays?: pulumi.Input<number>;
}
// 深いネストを避ける
interface DatabaseArgs {
instance: {
compute: { class: pulumi.Input<string> };
storage: { sizeGb: pulumi.Input<number> };
};
backup: {
config: { enabled: pulumi.Input<boolean>; retention: pulumi.Input<number> };
};
}
Union 型を使わない
Union 型はマルチ言語 SDK 生成を破壊します。Python、Go、C# は string | number を表現できません。
間違い:
interface MyArgs {
port: pulumi.Input<string | number>; // Python、Go、C# で失敗
}
正しい:
interface MyArgs {
port: pulumi.Input<number>; // 単一型、すべての場所で動作
}
複数の形式を受け入れる必要がある場合、別々のオプションプロパティを使用します:
interface StorageArgs {
sizeGb?: pulumi.Input<number>; // サイズを GB で指定
sizeMb?: pulumi.Input<number>; // またはサイズを MB で指定
}
関数またはコールバックは使わない
関数は言語境界を越えてシリアライズできません。
間違い:
interface MyArgs {
nameTransform: (name: string) => string; // シリアライズできない
}
正しい:
interface MyArgs {
namePrefix?: pulumi.Input<string>; // コールバックではなく設定
nameSuffix?: pulumi.Input<string>;
}
オプションプロパティにはデフォルト値を使用する
コンストラクタ内に賢明なデフォルトを設定し、コンシューマーは必要なものだけを設定します:
interface SecureBucketArgs {
enableVersioning?: pulumi.Input<boolean>; // デフォルトは true
enableEncryption?: pulumi.Input<boolean>; // デフォルトは true
blockPublicAccess?: pulumi.Input<boolean>; // デフォルトは true
}
class SecureBucket extends pulumi.ComponentResource {
constructor(name: string, args: SecureBucketArgs, opts?: pulumi.ComponentResourceOptions) {
super("myorg:index:SecureBucket", name, {}, opts);
const enableVersioning = args.enableVersioning ?? true;
const enableEncryption = args.enableEncryption ?? true;
const blockPublicAccess = args.blockPublicAccess ?? true;
// デフォルトを適用する...
}
}
// コンシューマーは必要なものだけをオーバーライドする
const bucket = new SecureBucket("data", { enableVersioning: false });
出力の公開
コンシューマーが必要なものだけを公開する
コンポーネントはしばしば多くの内部リソースを作成します。実装の詳細ではなく、コンシューマーが必要な値だけを公開してください。
間違い:
class Database extends pulumi.ComponentResource {
// すべてを公開 -- コンシューマーが実装の詳細を見る
public readonly cluster: aws.rds.Cluster;
public readonly primaryInstance: aws.rds.ClusterInstance;
public readonly replicaInstance: aws.rds.ClusterInstance;
public readonly subnetGroup: aws.rds.SubnetGroup;
public readonly securityGroup: aws.ec2.SecurityGroup;
public readonly parameterGroup: aws.rds.ClusterParameterGroup;
// ...
}
正しい:
class Database extends pulumi.ComponentResource {
// コンシューマーが必要なものだけを公開
public readonly endpoint: pulumi.Output<string>;
public readonly port: pulumi.Output<number>;
public readonly securityGroupId: pulumi.Output<string>;
constructor(name: string, args: DatabaseArgs, opts?: pulumi.ComponentResourceOptions) {
super("myorg:index:Database", name, {}, opts);
const sg = new aws.ec2.SecurityGroup(`${name}-sg`, { /* ... */ }, { parent: this });
const cluster = new aws.rds.Cluster(`${name}-cluster`, { /* ... */ }, { parent: this });
this.endpoint = cluster.endpoint;
this.port = cluster.port;
this.securityGroupId = sg.id;
this.registerOutputs({
endpoint: this.endpoint,
port: this.port,
securityGroupId: this.securityGroupId,
});
}
}
複合出力を派生させる
pulumi.interpolate または pulumi.concat を使用して派生値を構築します:
this.connectionString = pulumi.interpolate`postgresql://${args.username}:${args.password}@${cluster.endpoint}:${cluster.port}/${args.databaseName}`;
this.registerOutputs({ connectionString: this.connectionString });
コンポーネント設計パターン
オーバーライド可能な賢明なデフォルト
ベストプラクティスをデフォルトとしてコード化します。コンシューマーが特定の要件を持つ場合はオーバーライドできます。
interface SecureBucketArgs {
enableVersioning?: pulumi.Input<boolean>;
enableEncryption?: pulumi.Input<boolean>;
blockPublicAccess?: pulumi.Input<boolean>;
tags?: pulumi.Input<Record<string, pulumi.Input<string>>>;
}
class SecureBucket extends pulumi.ComponentResource {
public readonly bucketId: pulumi.Output<string>;
public readonly arn: pulumi.Output<string>;
constructor(name: string, args: SecureBucketArgs = {}, opts?: pulumi.ComponentResourceOptions) {
super("myorg:index:SecureBucket", name, {}, opts);
const bucket = new aws.s3.Bucket(`${name}-bucket`, {
tags: args.tags,
}, { parent: this });
// バージョニングはデフォルトで有効
if (args.enableVersioning !== false) {
new aws.s3.BucketVersioningV2(`${name}-versioning`, {
bucket: bucket.id,
versioningConfiguration: { status: "Enabled" },
}, { parent: this });
}
// 暗号化はデフォルトで有効
if (args.enableEncryption !== false) {
new aws.s3.BucketServerSideEncryptionConfigurationV2(`${name}-encryption`, {
bucket: bucket.id,
rules: [{ applyServerSideEncryptionByDefault: { sseAlgorithm: "AES256" } }],
}, { parent: this });
}
// パブリックアクセスはデフォルトでブロック
if (args.blockPublicAccess !== false) {
new aws.s3.BucketPublicAccessBlock(`${name}-public-access`, {
bucket: bucket.id,
blockPublicAcls: true,
blockPublicPolicy: true,
ignorePublicAcls: true,
restrictPublicBuckets: true,
}, { parent: this });
}
this.bucketId = bucket.id;
this.arn = bucket.arn;
this.registerOutputs({ bucketId: this.bucketId, arn: this.arn });
}
}
条件付きリソース作成
オプションの args を使用してサブリソース作成をゲートします:
interface WebServiceArgs {
image: pulumi.Input<string>;
port: pulumi.Input<number>;
enableMonitoring?: pulumi.Input<boolean>;
alarmEmail?: pulumi.Input<string>;
}
class WebService extends pulumi.ComponentResource {
constructor(name: string, args: WebServiceArgs, opts?: pulumi.ComponentResourceOptions) {
super("myorg:index:WebService", name, {}, opts);
const service = new aws.ecs.Service(`${name}-service`, {
// ...service config...
}, { parent: this });
// モニタリングが有効な場合のみアラームインフラを作成
if (args.enableMonitoring) {
const topic = new aws.sns.Topic(`${name}-alerts`, {}, { parent: this });
if (args.alarmEmail) {
new aws.sns.TopicSubscription(`${name}-alert-email`, {
topic: topic.arn,
protocol: "email",
endpoint: args.alarmEmail,
}, { parent: this });
}
new aws.cloudwatch.MetricAlarm(`${name}-cpu-alarm`, {
// ...alarm config referencing service...
alarmActions: [topic.arn],
}, { parent: this });
}
this.registerOutputs({});
}
}
コンポジション
より低レベルのコンポーネントから高レベルのコンポーネントを構築します。各レベルは単一の責任を管理します。
// 低レベルのコンポーネント
class VpcNetwork extends pulumi.ComponentResource {
public readonly vpcId: pulumi.Output<string>;
public readonly publicSubnetIds: pulumi.Output<string>[];
public readonly privateSubnetIds: pulumi.Output<string>[];
constructor(name: string, args: VpcNetworkArgs, opts?: pulumi.ComponentResourceOptions) {
super("myorg:index:VpcNetwork", name, {}, opts);
// ...VPC、サブネット、ルートテーブルを作成...
this.registerOutputs({ vpcId: this.vpcId });
}
}
// VpcNetwork を使用する高レベルのコンポーネント
class Platform extends pulumi.ComponentResource {
public readonly kubeconfig: pulumi.Output<string>;
constructor(name: string, args: PlatformArgs, opts?: pulumi.ComponentResourceOptions) {
super("myorg:index:Platform", name, {}, opts);
// 低レベルのコンポーネントを合成
const network = new VpcNetwork(`${name}-network`, {
cidrBlock: args.cidrBlock,
}, { parent: this });
const cluster = new aws.eks.Cluster(`${name}-cluster`, {
vpcConfig: {
subnetIds: network.privateSubnetIds,
},
}, { parent: this });
this.kubeconfig = cluster.kubeconfig;
this.registerOutputs({ kubeconfig: this.kubeconfig });
}
}
プロバイダーのパススルー
マルチリージョンまたはマルチアカウント設定の場合、明示的なプロバイダーを受け入れます。ComponentResourceOptions は子にプロバイダー設定を自動的に渡します:
// コンシューマーが別のリージョン用のプロバイダーを渡す
const usWest = new aws.Provider("us-west", { region: "us-west-2" });
const site = new StaticSite("west-site", { indexDocument: "index.html" }, {
providers: [usWest],
});
{ parent: this } の子は自動的にプロバイダーを継承します。コンポーネント内に追加のコードは不要です。
マルチ言語コンポーネント
コンポーネントが複数の Pulumi 言語 (TypeScript、Python、Go、C#、Java、YAML) から使用される場合、マルチ言語コンポーネントとしてパッケージ化します。
マルチ言語が必要ですか?
質問: 「誰かがこのコンポーネントをそれが作成された言語とは異なる言語から使用しますか?」
単一言語コンポーネント (パッケージ化は不要):
- チームが1つの言語を使用し、コンポーネントはそのコードベース内に留まる
- コンポーネントは単一プロジェクトまたはモノレポ内で内部
PulumiPlugin.yamlは不要 -- クラスを直接インポートするだけ
マルチ言語コンポーネント (パッケージ化が必要):
- 他のチームが異なる言語でコンポーネントを使用
- プラットフォームチームが言語を選択する開発者の抽象化を構築
- YAML コンシューマーはアクセスが必要 -- TypeScript で作成した場合でも、YAML プログラムはコンポーネントを使用するためにマルチ言語パッケージ化が必要
- 組織の共有コンポーネントライブラリを構築
- Pulumi プライベートレジストリまたはパブリックレジストリに公開することは一般的な理由ですが、マルチ言語サポートには必須ではありません
一般的な誤り: TypeScript プラットフォームチームが TypeScript ユーザーのみが使用できるコンポーネントを構築します。アプリケーション開発者が Python または YAML を使用する場合、マルチ言語パッケージ化なしではこれらのコンポーネントは見えません。
セットアップ
コンポーネントディレクトリに PulumiPlugin.yaml を作成してランタイムを宣言します:
runtime: nodejs
または Python の場合:
runtime: python
シリアライゼーション制約
マルチ言語互換性のため、args はシリアライズ可能である必要があります。これらの制約は作成言語に関係なく適用されます:
| 許可 | 許可されない |
|---|---|
string、number、boolean | Union 型 (string | number) |
Input<T> ラッパー | 関数とコールバック |
| プリミティブの配列とマップ | 複雑なネストジェネリック |
| 列挙型 | プラットフォーム固有の型 |
マルチ言語コンポーネントの使用
コンシューマーは pulumi package add でコンポーネントをインストールしますが、これはプロバイダープラグインを自動ダウンロードし、コンシューマーの言語でローカル SDK を生成し、Pulumi.yaml を更新します:
# Git リポジトリから
pulumi package add <git-repo-url>
# 特定のバージョンタグから
pulumi package add <git-repo-url>@v1.0.0
新規チェックアウトや CI 環境の場合、pulumi install を実行してすべてのパッケージ依存関係が利用可能であることを確認します。コンシューマーは SDK を手動で生成する必要はありません。
SDK を npm、PyPI などのパッケージマネージャーに公開する作成者は、オプションで pulumi package gen-sdk を使用して言語固有の SDK を生成し、公開することができます。ほとんどのコンポーネント作成者にはこれは不要です -- pulumi package add はコンシューマー側の SDK 生成を処理します。
エントリポイント
公開されたマルチ言語コンポーネントには、コンポーネントプロバイダープロセスをホストするエントリポイントが必要です。エントリポイントパターンは言語によって異なります。
TypeScript (runtime: nodejs):
index.ts からコンポーネントクラスをエクスポートします。別のエントリポイントファイルは不要です。Pulumi はエクスポートされたクラスを自動的に自省します。
// index.ts -- エクスポートがエントリポイント
export { StaticSite, StaticSiteArgs } from "./staticSite";
export { SecureBucket, SecureBucketArgs } from "./secureBucket";
Python (runtime: python):
すべてのコンポーネントクラスで component_provider_host を呼び出す __main__.py を作成します:
from pulumi.provider.experimental import component_provider_host
from static_site import StaticSite
from secure_bucket import SecureBucket
if __name__ == "__main__":
component_provider_host(
name="my-components",
components=[StaticSite, SecureBucket],
)
Go (runtime: go):
プロバイダーを構築および実行する main.go を作成します:
package main
import (
"context"
"fmt"
"os"
"github.com/pulumi/pulumi-go-provider/infer"
)
func main() {
p, err := infer.NewProviderBuilder().
WithComponents(
infer.ComponentF(NewStaticSite),
infer.ComponentF(NewSecureBucket),
).
Build()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
if err := p.Run(context.Background(), "my-components", "0.1.0"); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
C# (runtime: dotnet):
コンポーネントプロバイダーホストを提供する Program.cs を作成します:
using System.Threading.Tasks;
class Program
{
public static Task Main(string[] args) =>
Pulumi.Experimental.Provider.ComponentProviderHost.Serve(args);
}
すべての言語にわたる完全に動作する例については、https://github.com/mikhailshilkov/comp-as-comp を参照してください。
参考: https://www.pulumi.com/docs/iac/using-pulumi/pulumi-packages/
配布
対象ユーザーに基づいて配布方法を選択します:
| 対象ユーザー | 方法 | 方法 |
|---|---|---|
| 同じプロジェクト | 直接インポート | 標準言語インポート |
| 同じ組織 | プライベートレジストリ | Pulumi Cloud に pulumi package publish |
| 同じ組織 | Git リポジトリ | バージョンタグで pulumi package add <repo> |
| 言語エコシステム | パッケージマネージャー | npm、PyPI、NuGet、または Maven に公開 |
| パブリックコミュニティ | Pulumi Registry | pulumi/registry GitHub リポ経由で送信 |
Pulumi プライベートレジストリ
プライベートレジストリは組織のコンポーネント用の一元化されたカタログです。自動 API ドキュメント、バージョン管理、およびすべてのチームの発見可能性を提供します。
コンポーネントをプライベートレジストリに公開します:
pulumi package publish https://github.com/myorg/my-component --publisher myorg
v プレフィックス付きの git タグを使用してコンポーネントをバージョン管理します:
git tag v1.0.0
git push origin v1.0.0
公開時に README ファイルが必要です。Pulumi はレジストリ内のコンポーネントのドキュメントページとして使用します。
GitHub Actions から OIDC 認証を使用して公開を自動化します:
name: Publish Component
on:
push:
tags:
- "v*"
permissions:
id-token: write
contents: read
jobs:
publish:
runs-on: ubuntu-latest
env:
PULUMI_ORG: myorg
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pulumi/auth-actions@v1
with:
organization: ${{ env.PULUMI_ORG }}
requested-token-type: urn:pulumi:token-type:access_token:organization
- run: pulumi package publish https://github.com/${{ github.repository }} --publisher ${{ env.PULUMI_ORG }}
前提条件: このワークフローを使用する前に、Pulumi Cloud で GitHub OIDC 統合を設定します。
レジストリはプライベート GitHub および GitLab リポジトリをサポートします。非 OIDC セットアップの場合、GITHUB_TOKEN または GITLAB_TOKEN 環境変数で認証します。
プライベートレジストリは公開されたコンポーネント用の SDK ドキュメントを自動生成します。コンポーネントの入出力に型アノテーション (TypeScript の JSDoc、Python のドキュメント文字列、Go の Annotate() メソッド) を追加して、生成されたドキュメントを充実させます。
参考: https://www.pulumi.com/docs/idp/get-started/private-registry/
Git リポジトリ配布
コンシューマーがバージョンをピンできるようにリリースにタグを付けます:
git tag v1.0.0
git push origin v1.0.0
コンシューマーは以下でインストールします:
pulumi package add https://github.com/myorg/my-component@v1.0.0
パッケージマネージャー配布
ネイティブ依存関係管理のために言語固有のパッケージを公開します:
- npm: TypeScript/JavaScript の
npm publish - PyPI: Python の
twine upload - NuGet: .NET の
dotnet nuget push - Maven Central: Java の標準 Maven 公開
参考: https://www.pulumi.com/docs/iac/using-pulumi/pulumi-packages/
アンチパターン
| アンチパターン | 問題 | 修正 |
|---|---|---|
apply() 内のリソース | pulumi preview に表示されない | apply の外側にリソース作成を移動 (pulumi-best-practices プラクティス 1 を参照) |
registerOutputs() がない | コンポーネントが「作成中」で止まる | 常にコンストラクタの最後の行として呼び出す |
parent: this がない | 子が root レベルに表示される | すべての子リソースに { parent: this } を渡す |
| args の Union 型 | Python、Go、C# SDK を破壊 | 単一型を使用; バリアント用に別々のプロパティ |
| args の関数 | 言語境界を越えてシリアライズできない | コールバックではなく設定プロパティを使用 |
| ハードコードされた子名 | 複数インスタンスで衝突 | ${name}-suffix から名前を派生 |
| 公開が多すぎる出力 | 実装の詳細をリーク | コンシューマーが必要なものだけをエクスポート |
| 単一用途のコンポーネント | 不要な抽象化オーバーヘッド | パターンが繰り返されるまでインラインリソースを使用 |
| 深くネストされた args | 使用と進化が困難 | オプションプロパティを使用してインターフェースをフラットに保つ |
クイックリファレンス
| トピック | キーポイント |
|---|---|
| Type URN | <package>:<module>:<type>、モジュールは通常 index |
| コンストラクタ | super(type, name, {}, opts) その後子リソース その後 registerOutputs() |
| 子リソース | 常に { parent: this }、${name}-suffix から名前を派生 |
| Args インターフェース | Input<T> でラップ、union なし、関数なし、フラット構造 |
| 出力 | パブリック読み取り専用 Output<T> プロパティ、本質的なものだけをエクスポート |
| デフォルト | コンストラクタで ?? 演算子を使用して賢明なデフォルトを適用 |
| コンポジション | より低レベルのコンポーネントがより高レベルのものに合成 |
| マルチ言語 | PulumiPlugin.yaml + エントリポイント; コンシューマーは pulumi package add を使用 |
| 配布 | プライベートレジストリ、git タグ、パッケージマネージャー、または公開 Pulumi Registry |
関連スキル
- pulumi-best-practices: Output 処理、シークレット、エイリアスを含む一般的な Pulumi パターン
- pulumi-automation-api: 統合テストとマルチスタックワークフロー用のプログラム的な調整
- pulumi-esc: コンポーネント展開用の一元化されたシークレットと設定
参考
- https://www.pulumi.com/docs/iac/concepts/resources/components/
- https://www.pulumi.com/docs/iac/using-pulumi/pulumi-packages/
- https://www.pulumi.com/docs/idp/get-started/private-registry/
- https://www.pulumi.com/docs/iac/concepts/inputs-outputs/
- https://www.pulumi.com/docs/iac/concepts/resources/options/aliases/
ライセンス: Apache-2.0(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- pulumi
- リポジトリ
- pulumi/agent-skills
- ライセンス
- Apache-2.0
- 最終更新
- 不明
Source: https://github.com/pulumi/agent-skills / ライセンス: Apache-2.0
関連スキル
superfluid
Superfluidプロトコルおよびそのエコシステムに関するナレッジベースです。Superfluidについて情報を検索する際は、ウェブ検索の前にこちらを参照してください。対応キーワード:Superfluid、CFA、GDA、Super App、Super Token、stream、flow rate、real-time balance、pool(member/distributor)、IDA、sentinels、liquidation、TOGA、@sfpro/sdk、semantic money、yellowpaper、whitepaper
civ-finish-quotes
実質的なタスクが真に完了した際に、文明風の儀式的な引用句を追加します。ユーザーやエージェントが機能追加、リファクタリング、分析、設計ドキュメント、プロセス改善、レポート、執筆タスクといった実際の成果物を完成させるときに、明示的な依頼がなくても使用します。短い返信や小さな修正、未完成の作業には適用しません。
nookplot
Base(Ethereum L2)上のAIエージェント向け分散型調整ネットワークです。エージェントがオンチェーンアイデンティティを登録する、コンテンツを公開する、他のエージェントにメッセージを送る、マーケットプレイスで専門家を雇う、バウンティを投稿・請求する、レピュテーションを構築する、共有プロジェクトで協業する、リサーチチャレンジを解くことでNOOKをマイニングする、キュレーションされたナレッジを備えたスタンドアロンオンチェーンエージェントをデプロイする、またはアグリーメントとリワードで収益を得る場合に利用できます。エージェントネットワーク、エージェント調整、分散型エージェント、NOOKトークン、マイニングチャレンジ、ナレッジバンドル、エージェントレピュテーション、エージェントマーケットプレイス、ERC-2771メタトランザクション、Prepare-Sign-Relay、AgentFactory、またはNookplotが言及された場合にトリガーされます。
web3-polymarket
Polygon上でのPolymarket予測市場取引統合です。認証機能(L1 EIP-712、L2 HMAC-SHA256、ビルダーヘッダー)、注文発注(GTC/GTD/FOK/FAK、バッチ、ポストオンリー、ハートビート)、市場データ(Gamma API、Data API、オーダーブック、サブグラフ)、WebSocketストリーミング(市場・ユーザー・スポーツチャネル)、CTF操作(分割、統合、償却、ネガティブリスク)、ブリッジ機能(入金、出金、マルチチェーン)、およびガスレスリレイトランザクションに対応しています。AIエージェント、自動マーケットメーカー、予測市場UI、またはPolygraph上のPolymarketと統合するアプリケーション構築時に活用できます。
ethskills
Ethereum、EVM、またはブロックチェーン関連のリクエストに対応します。スマートコントラクト、dApps、ウォレット、DeFiプロトコルの構築、監査、デプロイ、インタラクションに適用されます。Solidityの開発、コントラクトアドレス、トークン規格(ERC-20、ERC-721、ERC-4626など)、Layer 2ネットワーク(Base、Arbitrum、Optimism、zkSync、Polygon)、Uniswap、Aave、Curveなどのプロトコルとの統合をカバーします。ガスコスト、コントラクトのデシマル設定、オラクルセキュリティ、リエントランシー、MEV、ブリッジング、ウォレット管理、オンチェーンデータの取得、本番環境へのデプロイ、プロトコル進化(EIPライフサイクル、フォーク追跡、今後の変更予定)といったトピックを含みます。
xxyy-trade
このスキルは、ユーザーが「トークン購入」「トークン売却」「トークンスワップ」「暗号資産取引」「取引ステータス確認」「トランザクション照会」「トークンスキャン」「フィード」「チェーン監視」「トークン照会」「トークン詳細」「トークン安全性確認」「ウォレット一覧表示」「マイウォレット」「AIスキャン」「自動スキャン」「ツイートスキャン」「オンボーディング」「IP確認」「IPホワイトリスト」「トークン発行」「自動売却」「損切り」「利益確定」「トレーリングストップ」「保有者」「トップホルダー」「KOLホルダー」などをリクエストした場合、またはSolana/ETH/BSC/BaseチェーンでXXYYを経由した取引について言及した場合に使用します。XXYY Open APIを通じてオンチェーン取引とデータ照会を実現します。