Skip to content

Commit 1bef6d4

Browse files
author
serverpod_cloud
committed
feat(scloud): f49d30abe104d413ceef015232c159861f2912f3
1 parent 45b956e commit 1bef6d4

5 files changed

Lines changed: 81 additions & 2 deletions

File tree

ground_control_client/lib/src/protocol/client.dart

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,24 @@ class EndpointAdminProcurement extends _i1.EndpointRef {
106106
{'userEmail': userEmail},
107107
);
108108

109+
/// Cancels the primary plan subscription of the user
110+
/// at the end of its current term.
111+
///
112+
/// If [terminateImmediately] is true, the subscription is terminated
113+
/// immediately. If the user still has any active resource products,
114+
/// a [ProcurementCancellationException] will be thrown.
115+
///
116+
/// Throws a [NoSubscriptionException] if the user has no subscription.
117+
/// Throws a [ProcurementCancellationException] if the subscription has
118+
/// already been cancelled or ended.
119+
_i2.Future<void> cancelPlan({
120+
required String userEmail,
121+
bool? terminateImmediately,
122+
}) => caller.callServerEndpoint<void>('adminProcurement', 'cancelPlan', {
123+
'userEmail': userEmail,
124+
'terminateImmediately': terminateImmediately,
125+
});
126+
109127
@Deprecated(
110128
'This endpoint to migrate to hackathon plan is no longer supported.',
111129
)
@@ -665,7 +683,7 @@ class EndpointPlans extends _i1.EndpointRef {
665683
/// Cancels the primary plan subscription of the user.
666684
///
667685
/// - Throws [ProcurementCancellationException] if the cancellation fails,
668-
/// e.g. if the subscription still has active resources.
686+
/// e.g. if the subscription still has active resources or is already cancelled.
669687
/// - Throws [NoSubscriptionException] if the user has no subscription.
670688
_i2.Future<void> cancelPlan() =>
671689
caller.callServerEndpoint<void>('plans', 'cancelPlan', {});

serverpod_cloud_cli/lib/command_runner/commands/admin/admin_product_commands.dart

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class AdminProductCommand extends CloudCliCommand {
1414
AdminProductCommand({required super.logger}) {
1515
addSubcommand(AdminListProcuredCommand(logger: logger));
1616
addSubcommand(AdminProcurePlanCommand(logger: logger));
17+
addSubcommand(AdminCancelPlanCommand(logger: logger));
1718
}
1819
}
1920

@@ -136,3 +137,48 @@ class AdminProcurePlanCommand extends CloudCliCommand<AdminProcurePlanOption> {
136137
);
137138
}
138139
}
140+
141+
enum AdminCancelPlanOption<V> implements OptionDefinition<V> {
142+
user(UserEmailOption(argPos: 0, mandatory: true)),
143+
terminateImmediately(
144+
FlagOption(
145+
argName: 'immediately',
146+
helpText: 'Terminate the subscription immediately.',
147+
negatable: false,
148+
defaultsTo: false,
149+
),
150+
);
151+
152+
const AdminCancelPlanOption(this.option);
153+
154+
@override
155+
final ConfigOptionBase<V> option;
156+
}
157+
158+
class AdminCancelPlanCommand extends CloudCliCommand<AdminCancelPlanOption> {
159+
@override
160+
final name = 'cancel-plan';
161+
162+
@override
163+
final description = "Cancels a user's subscription.\n";
164+
165+
AdminCancelPlanCommand({required super.logger})
166+
: super(options: AdminCancelPlanOption.values);
167+
168+
@override
169+
Future<void> runWithConfig(
170+
final Configuration<AdminCancelPlanOption> commandConfig,
171+
) async {
172+
final userEmail = commandConfig.value(AdminCancelPlanOption.user);
173+
final terminateImmediately = commandConfig.value(
174+
AdminCancelPlanOption.terminateImmediately,
175+
);
176+
177+
await ProductAdminCommands.cancelPlan(
178+
runner.serviceProvider.cloudApiClient,
179+
logger: logger,
180+
userEmail: userEmail,
181+
terminateImmediately: terminateImmediately,
182+
);
183+
}
184+
}

serverpod_cloud_cli/lib/command_runner/completion/completion_script_carapace.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ commands:
114114
-c, --concurrency=: "Number of concurrent files processed when zipping the project."
115115
--dry-run: "Do not actually deploy, just print the deployment steps."
116116
--show-files: "Display the file tree that will be uploaded."
117+
-o, --output=: "Save the deployment zip file to the specified path. Must end with .zip"
117118
118119
- name: variable
119120

serverpod_cloud_cli/lib/command_runner/completion/completion_script_completely.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,7 @@ _scloud_completions() {
869869
;;
870870
871871
'deploy'*)
872-
while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_scloud_completions_filter "--quiet -q --verbose -v --analytics --no-analytics -a --version --token --project-dir -d --project-config-file --timeout --yes --project -p --concurrency -c --dry-run --show-files")" -- "$cur")
872+
while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_scloud_completions_filter "--quiet -q --verbose -v --analytics --no-analytics -a --version --token --project-dir -d --project-config-file --timeout --yes --project -p --concurrency -c --dry-run --show-files --output -o")" -- "$cur")
873873
;;
874874
875875
'secret'*)

serverpod_cloud_cli/lib/commands/admin/product_admin.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,18 @@ abstract class ProductAdminCommands {
4040
newParagraph: true,
4141
);
4242
}
43+
44+
static Future<void> cancelPlan(
45+
final Client cloudApiClient, {
46+
required final CommandLogger logger,
47+
required final String userEmail,
48+
final bool? terminateImmediately,
49+
}) async {
50+
await cloudApiClient.adminProcurement.cancelPlan(
51+
userEmail: userEmail,
52+
terminateImmediately: terminateImmediately,
53+
);
54+
55+
logger.success("The user's plan has been cancelled.", newParagraph: true);
56+
}
4357
}

0 commit comments

Comments
 (0)