jolly-megabyte-6233
01/29/2025, 4:12 PM// USAGE EXAMPLE
const childModel = new AssetModel("test-child-1", {
name: "some-child-model",
description: "some-child-model",
externalId: "some-child-model",
})
const assetModel = new AssetModel("test-1", {
name: "some-asset-model",
description: "some-asset-model",
externalId: "some-asset-model",
properties: [
{
name: "prop-2",
externalId: "SAM-prop-1",
dataType: PropertyDataType.DOUBLE,
unit: "someNewUnit",
},
],
children: [
{
name: "asset-model-child",
externalId: "asset-model-child",
// !!! The next line is what causes the failure: `childModel.externalId` is `undefined` when pulumi runs the program
modelId: childModel.externalId.apply(externalId),
},
],
})
And here's the implementation my resource + provider (some implementation details omitted):
export interface AssetModelProviderArgs {
/** The name of the asset model */
name: string
/** An external id to reference this asset model */
externalId: string
/** The description of the asset model */
description: string
/** The properties of the asset model */
properties?: AssetModelProperty[]
/** The child asset model associations of the asset model */
children?: AssetModelChild[]
}
export interface AssetModelProperty {
/** The name of the asset model property */
name: string
/** An external id to reference this asset model property */
externalId: string
/** The data type of the asset model property */
dataType: PropertyDataType
/** The unit of the asset model property */
unit?: string
}
export interface AssetModelChild {
/** The name of the child asset model association */
name: string
/** An external id to reference this child asset model association */
externalId: string
/** The external id of the child asset model */
modelId: SitewiseId
}
export interface AssetModelProviderOuts extends AssetModelProviderArgs {
arn: string
}
const readAssetModelOuts = async (
id: string,
): Promise<AssetModelProviderOuts | undefined> => {
let readResponse: DescribeAssetModelResponse | null = null
try {
readResponse = await getSitewiseClient().assetModel.read({
assetModelId: id,
})
} catch (error) {
if (error instanceof AxiosError && error.response?.status === 404) {
return undefined
}
throw error
}
const assetModel: AssetModelProviderArgs = {
name: readResponse.assetModelName!,
externalId: readResponse.assetModelExternalId!,
description: readResponse.assetModelDescription!,
properties: (readResponse.assetModelProperties ?? []).map((property) => ({
name: property.name!,
externalId: property.externalId!,
dataType: property.dataType!,
unit: property.unit,
})),
children: (readResponse.assetModelHierarchies ?? []).map((hierarchy) => ({
name: hierarchy.name!,
externalId: hierarchy.externalId!,
modelId: uuid(hierarchy.childAssetModelId!),
})),
}
return {
...assetModel,
arn: readResponse.assetModelArn!,
}
}
export interface AssetModelArgs {
name: Input<string>
description: Input<string>
externalId: Input<string>
properties?: Input<AssetModelProviderArgs["properties"]>
children?: AsInput<AssetModelChild>[]
}
export const assetModelProvider: dynamic.ResourceProvider<
AssetModelProviderArgs,
AssetModelProviderOuts
> = {
async create(args) {
// ... details omitted
return {
id,
outs: await readAssetModelOuts(id),
}
},
async read(id, outs) {
return {
id,
props: outs ? await readAssetModelOuts(id) : undefined,
}
},
async diff(_, oldOuts, newArgs) {
// ... details omitted
return {
changes: !deepEqual(relevantOuts, relevantArgs),
stables: ["id", "arn", "externalId"],
}
},
async update(id, _, newArgs) {
// ... details omitted
return {
outs: await readAssetModelOuts(id),
}
},
async delete(id) {
// Note: This is not sufficient to delete models that contribute to a property formula in a parent.
await getSitewiseClient().assetModel.delete({ assetModelId: id })
},
}
export class AssetModel extends dynamic.Resource {
// args
public readonly name!: Output<AssetModelProviderOuts["name"]>
public readonly description!: Output<AssetModelProviderOuts["description"]>
public readonly externalId!: Output<AssetModelProviderOuts["externalId"]>
// outs
public readonly arn!: Output<AssetModelProviderOuts["arn"]>
constructor(
name: string,
args: AssetModelArgs,
opts?: CustomResourceOptions,
) {
super(assetModelProvider, `xxx:asset-model:${name}`, args, opts)
}
}
What's the issue here?
(I have checked the pulumi state JSON file and the externalId
for the child model is set at some point.)magnificent-eve-10499
01/29/2025, 5:07 PMconst assetModel = new AssetModel("test-1", {
name: "some-asset-model",
description: "some-asset-model",
externalId: "some-asset-model",
properties: [
{
name: "prop-2",
externalId: "SAM-prop-1",
dataType: PropertyDataType.DOUBLE,
unit: "someNewUnit",
},
],
children: [
{
name: "asset-model-child",
externalId: "asset-model-child",
// !!! The next line is what causes the failure: `childModel.externalId` is `undefined` when pulumi runs the program
modelId: childModel.externalId.apply(externalId),
},
],
},
{ dependsOn: [ childModel ] },
)
jolly-megabyte-6233
01/29/2025, 5:23 PMundefined
even when adding an explicit dependency,
(Besides: I was expecting that pulumi would be able to derive the dependency from the usage of an output as part of the input of a resource?)magnificent-eve-10499
01/29/2025, 9:58 PMimport * as pulumi from '@pulumi/pulumi';
import * as dockerbuild from '@pulumi/docker-build';
import { marketingcr, acrUsername, acrPassword, registryUrl } from './registries/acrRegistry';
const config = new pulumi.Config();
const imageTag = config.get('imageTag') || 'latest';
const imageNames = [
'marketing-nginx',
'marketing-mautic_web',
];
const imageBuilds: { [key: string]: dockerbuild.Image } = {};
// Wait for the ACR to be created before proceeding
marketingcr.name.apply(acrName => {
registryUrl.apply(registry => {
for (const imageName of imageNames) {
const fullImageName = pulumi.interpolate`${registry}/${imageName}:${imageTag}`;
// Define the dockerbuild.Image resource
imageBuilds[imageName] = new dockerbuild.Image(
imageName,
{
context: {
location: '../mautic',
},
push: true,
dockerfile: {
location: `../mautic/${imageName}.dockerfile`,
},
platforms: ['linux/amd64'],
registries: [{
address: registry,
username: acrUsername,
password: acrPassword,
}],
tags: [fullImageName],
});
}
});
});
// Export the image builds so they can be used elsewhere in the Pulumi stack
export { imageBuilds };
So maybe you could nest the parent in the child like:
childModel.externalId.apply(externalId => {
const assetModel = new AssetModel("test-1", {
name: "some-asset-model",
description: "some-asset-model",
externalId: "some-asset-model",
properties: [
{
name: "prop-2",
externalId: "SAM-prop-1",
dataType: PropertyDataType.DOUBLE,
unit: "someNewUnit",
},
],
children: [
{
name: "asset-model-child",
externalId: "asset-model-child",
// !!! The next line is what causes the failure: `childModel.externalId` is `undefined` when pulumi runs the program
modelId: externalId,
},
],
},
},)
)
I believe that If externalID is still undefined this way, then it doesn't exist before running this statement.No matter how you like to participate in developer communities, Pulumi wants to meet you there. If you want to meet other Pulumi users to share use-cases and best practices, contribute code or documentation, see us at an event, or just tell a story about something cool you did with Pulumi, you are part of our community.
Powered by