Skip to content

Commit 77c9c04

Browse files
authored
upcoming: [M3-10385] - Add Linode Interface support for Linode Create CLI Codesnippets tool (linode#12591)
* support for CLI * Added changeset: Add Linode Interface support for Linode CLI codesnippets tool * consolidate type import
1 parent 97733f5 commit 77c9c04

File tree

5 files changed

+25
-62
lines changed

5 files changed

+25
-62
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/manager": Upcoming Features
3+
---
4+
5+
Add Linode Interface support for Linode CLI codesnippets tool ([#12591](https://github.com/linode/manager/pull/12591))

packages/manager/src/features/Kubernetes/KubernetesPlansPanel/NodePoolConfigDrawer.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ export const NodePoolConfigDrawer = (props: Props) => {
6262
} = props;
6363

6464
// Use the node pool state from the main create flow from.
65-
const { control: parentFormControl } = useFormContext<CreateClusterFormValues>();
65+
const { control: parentFormControl } =
66+
useFormContext<CreateClusterFormValues>();
6667
const _nodePools = useWatch({
6768
control: parentFormControl,
6869
name: 'nodePools',

packages/manager/src/features/Linodes/LinodeCreate/ApiAwarenessModal/LinodeCLIPanel.tsx

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Notice, Typography } from '@linode/ui';
1+
import { Typography } from '@linode/ui';
22
import React, { useMemo } from 'react';
33
import { useFormContext } from 'react-hook-form';
44

@@ -26,10 +26,6 @@ export const LinodeCLIPanel = ({
2626
}: LinodeCLIPanelProps) => {
2727
const createType = useGetLinodeCreateType();
2828

29-
// @TODO - Linode Interfaces
30-
// DX support (CLI, integrations, sdks) for Linode Interfaces is not yet available. Remove this when it is.
31-
const showDXCodeSnippets = payLoad.interface_generation !== 'linode';
32-
3329
const linodeCLIAction = createType;
3430

3531
const { getValues } = useFormContext<LinodeCreateFormValues>();
@@ -68,17 +64,7 @@ export const LinodeCLIPanel = ({
6864
</Link>
6965
.
7066
</Typography>
71-
{!showDXCodeSnippets && (
72-
<Notice
73-
spacingTop={16}
74-
text="Linode CLI support to create Linodes using Linode Interfaces is
75-
coming soon."
76-
variant="info"
77-
/>
78-
)}
79-
{showDXCodeSnippets && (
80-
<CodeBlock analyticsLabel={title} code={cliCommand} language={'bash'} />
81-
)}
67+
<CodeBlock analyticsLabel={title} code={cliCommand} language={'bash'} />
8268
</SafeTabPanel>
8369
);
8470
};

packages/manager/src/utilities/codesnippets/generate-cli.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const linodeDataForCLI = `
4444
--type ${linodeRequest.type} \\
4545
--authorized_users Linny \\
4646
--authorized_users Gritty \\
47-
--interfaces.ipam_address null --interfaces.ipv4.nat_1_1 \"any\" --interfaces.ipv4.vpc \"123\" --interfaces.label null --interfaces.primary true --interfaces.purpose \"vpc\" --interfaces.subnet_id 8296 \\
47+
--interfaces '[{"ipv4":{"nat_1_1":"any","vpc":"123"},"primary":true,"purpose":"vpc","subnet_id":8296}]' \\
4848
--metadata.user_data="cmVrbmpnYmloZXVma2xkbQpqZXZia2Y=" \\
4949
--placement_group.id 1234 \\
5050
--stackscript_data '{"gh_username": "linode"}' \\

packages/manager/src/utilities/codesnippets/generate-cli.ts

Lines changed: 15 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
import type { PlacementGroup } from '@linode/api-v4';
2-
import type {
3-
ConfigInterfaceIPv4,
4-
UserData,
5-
} from '@linode/api-v4/lib/linodes/types';
1+
import type { PlacementGroup, UserData } from '@linode/api-v4';
62

73
// Credit: https://github.com/xxorax/node-shell-escape
84
function escapeStringForCLI(s: string): string {
@@ -21,47 +17,18 @@ const convertObjectToCLIArg = (data: null | {}) => {
2117
return `'${JSON.stringify(data).replace(':', ': ')}'`;
2218
};
2319

24-
const parseObject = (key: string, value: {}) => {
25-
// M3-7638: The Linode CLI does not currently accept interfaces.ipv4 as an object so we need to make them separate arguments
26-
const parseIpv4Object = (_key: string, _value: ConfigInterfaceIPv4) => {
27-
const ipv4ValueStrings = [];
28-
if (_value.nat_1_1) {
29-
ipv4ValueStrings.push(
30-
`--${key}.${_key}.nat_1_1 ${JSON.stringify(_value.nat_1_1)}`
31-
);
32-
}
33-
if (_value.vpc) {
34-
ipv4ValueStrings.push(
35-
`--${key}.${_key}.vpc ${JSON.stringify(_value.vpc)}`
36-
);
37-
}
38-
return ipv4ValueStrings.join(' ');
39-
};
40-
41-
const result = Object.entries(value)
42-
.map(([_key, _value]) => {
43-
if (_key === 'ipv4') {
44-
return parseIpv4Object(_key, _value as ConfigInterfaceIPv4);
45-
}
46-
return `--${key}.${_key} ${JSON.stringify(_value)}`;
47-
})
48-
.filter((string) => string.length > 0)
49-
.join(' ');
50-
return result.padStart(result.length + 2);
51-
};
52-
5320
const parseArray = (key: string, value: any[]) => {
5421
const results: string[] = [];
5522
if (key === 'interfaces') {
56-
results.push(
57-
value
58-
.map((item) => {
59-
// M3-7638: vpc_id is not a valid argument. The subnet_id will be used in the backend to implicitly determine the VPC ID
60-
delete item.vpc_id;
61-
return parseObject('interfaces', item);
62-
})
63-
.join('\\\n')
64-
);
23+
const json = value.map((item) => {
24+
// M3-7638: vpc_id is not a valid argument. The subnet_id will be used in the backend to implicitly determine the VPC ID
25+
delete item.vpc_id;
26+
return Object.fromEntries(
27+
Object.entries(item).filter(([_, value]) => value !== null)
28+
);
29+
});
30+
31+
results.push(` --${key} ${escapeStringForCLI(JSON.stringify(json))}`);
6532
} else {
6633
value.forEach((item) => {
6734
results.push(` --${key} ${escapeStringForCLI(item)}`);
@@ -118,7 +85,11 @@ export const generateCLICommand = (
11885
const dataForCLI = Object.entries(data).reduce(dataEntriesReduce, []);
11986

12087
if (linodeCLIAction === 'Clone Linode') {
121-
return `linode-cli linodes clone ${sourceLinodeID} \\\n${dataForCLI.join(
88+
const cloneDataForCLI = dataForCLI.filter(
89+
(entry) =>
90+
!entry.includes('--firewall_id') && !entry.includes('--interfaces')
91+
);
92+
return `linode-cli linodes clone ${sourceLinodeID} \\\n${cloneDataForCLI.join(
12293
' \\\n'
12394
)}`;
12495
}

0 commit comments

Comments
 (0)