Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions powershell/cmdlets/class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,9 @@ export class CmdletClass extends Class {
// implement part of the IContext
this.implementIContext();

// Change Safety: emit codegen-owned static parameters on write-verb cmdlets
this.implementChangeSafetyParameters();

// add constructors
this.implementConstructors();

Expand Down Expand Up @@ -1622,6 +1625,39 @@ export class CmdletClass extends Class {
extensibleParametersProp.get = toExpression(`${extensibleParameters.value} `);
this.add(extensibleParametersProp);
}
private implementChangeSafetyParameters() {
// Change Safety (codegen-owned static parameters): only azure management-plane (ARM)
// write-verb cmdlets (PUT/POST/DELETE/PATCH) expose the opt-in Change Safety parameters.
// The parameter values are read by the module-level HTTP pipeline step (in Az.Accounts)
// from the cmdlet's BoundParameters, so no runtime-wired delegate is required here.
// Opt-in per module via `change-safety: true` in the module readme (default off), so the
// 180+ module rollout is deliberate rather than triggered by any unrelated regeneration.
if (!this.state.project.changeSafety) {
return;
}
if (!this.state.project.azure) {
return;
}
// Change Safety is a management-plane concept; skip data-plane modules, which target a
// custom service endpoint (identified by an endpoint-resource-id-key-name). This matches
// the data-plane detection used in module-class.ts (isDataPlane).
if (this.state.project.endpointResourceIdKeyName) {
return;
}
const httpMethod = (this.apiCall.requests?.[0]?.protocol.http?.method ?? '').toLowerCase();
if (!['put', 'post', 'delete', 'patch'].includes(httpMethod)) {
return;
}

const acquirePolicyToken = this.add(new Property('AcquirePolicyToken', SwitchParameter, { attributes: [], description: 'Acquire an Azure Policy token automatically for this resource operation.' }));
acquirePolicyToken.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'HelpMessage = "Acquire an Azure Policy token automatically for this resource operation."'] }));
acquirePolicyToken.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Azure`] }));

const changeReference = this.add(new Property('ChangeReference', dotnet.String, { attributes: [], description: 'The change reference resource ID for this resource operation.' }));
changeReference.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'HelpMessage = "The change reference resource ID for this resource operation."'] }));
changeReference.add(new Attribute(ValidateNotNull));
changeReference.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Azure`] }));
}
private implementIEventListener() {
const $this = this;
const cts = this.add(new Field('_cancellationTokenSource', System.Threading.CancellationTokenSource, {
Expand Down
6 changes: 6 additions & 0 deletions powershell/internal/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ export class Project extends codeDomProject {
public modelCmdletFolder!: string;
public endpointResourceIdKeyName!: string;
public endpointSuffixKeyName!: string;
public changeSafety!: boolean;

public customFolder!: string;
public utilsFolder!: string;
Expand Down Expand Up @@ -334,6 +335,11 @@ export class Project extends codeDomProject {
// configuration for whether to use fixed array in generated code of model, default is false
this.fixedArray = await this.state.getValue('fixed-array', false);

// Change Safety: opt-in per module. When true, azure management-plane write-verb cmdlets get the
// -AcquirePolicyToken / -ChangeReference parameters. Default false so the rollout is controlled
// (a module opts in, alongside bumping its Az.Accounts minimum), not organic on every regeneration.
this.changeSafety = await this.state.getValue('change-safety', false);

// File paths
this.csproj = await this.state.getValue('csproj');
this.dll = await this.state.getValue('dll');
Expand Down
Loading