I tried using dynamic provider as a workaround for...
# general
m
I tried using dynamic provider as a workaround for my use case on cloudflare API which is not officially supported yet: 1. create allow rule and block rule using teamsrule resource from the official cloudflare Pulumi provider 2. POST request to /access/apps to create a "private_dns" type application 3. PUT request to /access/app_gateway_rules to bind allow rule and block rule created in 1 to the application created in 2 The create method works as fine because the application was created and the rules were bind successfully. However the plan always show there's a change in this dynamic resource. How can I find out what "makes" Pulumi thinks that there's a change?
l
Hey 👋 What does your
Diff
implementation look like?
m
Copy code
async diff(id: string, olds: any, news?: any) {
        const changes = Object.keys(news).some(key => {
            // Skip the comparison for the 'updated_at' property
            if (key === "updated_at") {
                return false;
            }
            return JSON.stringify(olds[key]) !== JSON.stringify(news[key]);
        });
        return {
            changes
        }
    }
the output shows "updated_at" was updated each time after the apply, so I tried to skip it
l
Did that work? There is potentially the fact that
stringify
will not be stable if key orders in the nested JSON are not stable (for instance)
m
uh...what do you mean by work? disclaimer: I don't have a read method yet
l
I meant if removing
updated_at
from the equation helped.
The lack of
read
shouldn't affect this I don't think.
diff
is going to be called with old data (from the Pulumi state -- nothing to do with the "cloud" state, which is what
read
returns) and the new "goal state" (what you've written in the program)
m
no, it wasn't there previously, and it doesn't work even after adding it
l
OK then I would be minded to investigate your stringification -- perhaps logging out
JSON.stringify(olds[key])
and
JSON.stringify(news[key])
will shed some light.
m
Copy code
~ pulumi-nodejs:dynamic:Resource: (update)
            [id=string]
            [urn=string]
            allowRuleId       : "string"
            app               : "string"
            appLauncherVisible: false
            blockRuleId       : "string"
            private_address   : "domain"
            tenantId          : "string"
            --outputs:--
          - allowRuleId         : "string"
          - app                 : "string"
          - appLauncherVisible  : false
          + app_launcher_visible: false
          + aud                 : "string"
          - blockRuleId         : "string"
          + created_at          : "0001-01-01T00:00:00Z"
          + gateway_rules       : [
          +     [0]: {
                  + id: "string"
                }
          +     [1]: {
                  + id: "string"
                }
            ]
          + id                  : "string"
          + name                : "string"
          + uid                 : "string"
          + updated_at          : "2024-06-05T10:39:16Z"
I've added a read method and this is the new log, is it due to a change in the output that forces an update? Is this something that I need to change in the return or outs in the create/ update method?
by the way, how can I log the value of
JSON.stringify(olds[key])
and
JSON.stringify(news[key])
in the diff method? it doesn't seem to display anything in the plan. I tried console.log(changes) before but no luck:
Copy code
async diff(id: string, olds: any, news?: any) {
        const changes = Object.keys(news).some(key => {
            // Skip the comparison for the 'updated_at' property
            if (key === "updated_at") {
                return false;
            }
            return JSON.stringify(olds[key]) !== JSON.stringify(news[key]);
        });
        console.log(changes)
        return {
            changes
        }
    }
l
If you do
console.log
and pass
--logflow --logtostderr
to the
pulumi
commands, do you see the logs?
m
I run Pulumi on Spacelift, is there a way that I can inject these as environment variable or the Pulumi.yaml file?
l
I'm not familiar with Spacelift but reading their docs it doesn't appear so. Does Spacelift prevent you from running Pulumi locally?
(E.g. just to test a deployment)
m
there's a task which I can run the preview manually, let me check further, thanks for your help!
l
All good 🙂
m
Copy code
~ pulumi-nodejs:dynamic:Resource: (refresh)
            [id=string]
            [urn=urn:pulumi:string]
            --outputs:--
          + app               : "string"
          - appId             : "string"
          + appLauncherVisible: true
          + private_address   : "string"
          + tags              : [
          +     [0]: "string"
          +     [1]: "string"
            ]
          + type              : "private_dns"
The logs above is shown in the plan, I suppose I need to add these attributes in the outputs of create or update?
l
Outputs shouldn't matter for
Diff
. When Pulumi calls
Diff
, it passes two things: • "Old" -- this is the inputs Pulumi has in its state file (so in essence, the last time it ran the program, what the inputs were) • "New" -- this is the inputs that are now specified in the program (so in essence, what the "code says now") So: • If some of your inputs are outputs of other resources, those resources may change and trigger your diff, but your outputs are not going to be involved, if that makes sense. • Your diff will be comparing those two sets of inputs and working out if there is a change
Read
is used in a few cases. Two common ones are: • When you perform an
import
, Pulumi tries to
Read
the state of the resource you are importing from the cloud provider. • When you perform a
refresh
, Pulumi tries to
Read
all your resources and compare what it finds with what it has in state
m
Copy code
eventSink::Info(<{%reset%}>Key: allowRuleId, Old Value: undefined, New Value: "string"
eventSink::Info(<{%reset%}>Key: app, Old Value: undefined, New Value: "string"
eventSink::Info(<{%reset%}>Key: appLauncherVisible, Old Value: undefined, New Value: true
eventSink::Info(<{%reset%}>Key: blockRuleId, Old Value: undefined, New Value: "string"
eventSink::Info(<{%reset%}>Key: tenantId, Old Value: undefined, New Value: "string"
finally managed to print out the keys and I think this is the root cause, I suppose I need to add those keys as part of the output in my create method?
l
So the return value of your
create
will end up in state, yes (as will
update
), and those are the values that will come in as
old
each time
diff
is called (with
new
being those in the current version of the program)
m
finally no more changes shown 🙏 @lively-crayon-44649
l
Great!