Skip to content
Merged
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
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Hypershift ton OpenStack CLI Assistant
# Hypershift CLI Assistant

Click [here](https://shiftstack.github.io/hcp-cli-assistant/) to open the assistant.

An interactive web UI wizard that helps users generate the correct `hcp create cluster openstack` command for deploying **HyperShift on OpenStack**.
An interactive web UI wizard that helps users generate the correct `hcp create cluster` commands.
The assistant guides users step-by-step through required and optional configurations, ensuring a smooth setup experience.

![UI screenshot](screenshot.png?raw=true "UI screenshot")
![UI demo](demo.gif?raw=true "UI demo")

## Features
- Step-by-step wizard for easy input
Expand Down Expand Up @@ -46,4 +46,4 @@ This project is open-source and available under the **Apache 2.0 License**.

---

Developed for HyperShift on OpenStack users.
Developed for HyperShift users.
Binary file added demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="/dist/styles.css" rel="stylesheet">
<title>HyperShift on OpenStack - CLI assistant</title>
<title>HyperShift CLI assistant</title>
</head>
<body>
<div id="root"></div>
Expand Down
Binary file removed screenshot.png
Binary file not shown.
173 changes: 172 additions & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ export default function HcpCliAssistant() {
// Platform config
const platforms = useMemo(() => [
{ value: "openstack", label: "OpenStack" },
{ value: "aws", label: "AWS" },
// Future platforms can be added here
// { value: "aws", label: "AWS" },
// { value: "azure", label: "Azure" },
], []);

Expand All @@ -178,6 +178,12 @@ export default function HcpCliAssistant() {
"OpenStack Node Configuration",
"Review & Generate Command"
],
aws: [
"AWS Node Configuration",
"AWS Storage Configuration",
"AWS Network Configuration",
"Review & Generate Command"
],
// Add more platform steps as they become available
}), []);

Expand Down Expand Up @@ -205,6 +211,16 @@ export default function HcpCliAssistant() {
nodeImageName: "",
dnsNameservers: "",
additionalPorts: "[]", // Initialize as string to avoid JSON parsing issues

// AWS specific fields
awsInstanceType: "",
awsInstanceProfile: "",
awsSubnetId: "",
awsSecurityGroupId: "",
awsRootVolumeSize: "120",
awsRootVolumeType: "gp3",
awsRootVolumeIops: "",
awsRootVolumeKmsKey: "",
});

// Get steps based on selected platform - memoize to prevent recalculation
Expand Down Expand Up @@ -333,6 +349,17 @@ export default function HcpCliAssistant() {
}
}

if (form.platform === "aws") {
const platformStep = step - 2; // Adjust for common steps

switch (platformStep) {
case 0: // AWS Node Configuration
return form.awsInstanceType.trim() !== "" && form.awsInstanceProfile.trim() !== "";
default:
return true;
}
}

return false;
}, [step, form, platformSteps, parsePorts]);

Expand Down Expand Up @@ -414,6 +441,55 @@ export default function HcpCliAssistant() {
return cmd;
}

if (form.platform === "aws") {
let cmd = `hcp create cluster aws \
--name ${form.name} \
--base-domain ${form.baseDomain} \
--node-pool-replicas ${form.nodePoolReplicas} \
--pull-secret ${form.pullSecret} \
--ssh-key ${form.sshKey} \
--instance-type ${form.awsInstanceType}`;

// Add optional AWS parameters
if (form.awsInstanceType) {
cmd += ` \
--instance-type ${form.awsInstanceType}`;
}

if (form.awsInstanceProfile) {
cmd += ` \
--instance-profile ${form.awsInstanceProfile}`;
}

if (form.awsSubnetId) {
cmd += ` \
--subnet-id ${form.awsSubnetId}`;
}

if (form.awsRootVolumeSize && form.awsRootVolumeSize !== "120") {
cmd += ` \
--root-volume-size ${form.awsRootVolumeSize}`;
}

if (form.awsRootVolumeType && form.awsRootVolumeType !== "gp3") {
cmd += ` \
--root-volume-type ${form.awsRootVolumeType}`;
}

if (form.awsRootVolumeIops) {
cmd += ` \
--root-volume-iops ${form.awsRootVolumeIops}`;
}

if (form.awsRootVolumeKmsKey) {
cmd += ` \
--root-volume-kms-key ${form.awsRootVolumeKmsKey}`;
}

cmd = cmd.replace(/\s+/g, ' ').trim();
return cmd;
}

return "Platform command generation not implemented";
}, [form, parsePorts]);

Expand Down Expand Up @@ -657,6 +733,86 @@ export default function HcpCliAssistant() {
</div>
);

const renderAwsNodeConfigStep = () => (
<>
<InputWithTooltip
name="awsInstanceType"
placeholder="Instance Type (required). Example: m5.xlarge"
value={form.awsInstanceType}
onChange={handleChange}
required
tooltip="The AWS EC2 instance type to use for worker nodes in your cluster."
/>

<InputWithTooltip
name="awsInstanceProfile"
placeholder="Instance Profile (required). Example: my-instance-profile"
value={form.awsInstanceProfile}
onChange={handleChange}
required
tooltip="The AWS IAM instance profile for the node pool. This profile must have the necessary permissions for OpenShift to operate."
/>
</>
);

const renderAwsStorageConfigStep = () => (
<>
<InputWithTooltip
name="awsRootVolumeType"
placeholder="Root Volume Type. Example: gp3"
value={form.awsRootVolumeType}
onChange={handleChange}
tooltip="The EBS volume type to use for worker node root volumes. Common types: gp3, io1, io2, etc."
/>

<InputWithTooltip
type="number"
name="awsRootVolumeSize"
placeholder="Root Volume Size. Example: 120"
value={form.awsRootVolumeSize}
onChange={handleChange}
tooltip="The size of the root volume in GB for worker nodes."
/>

<InputWithTooltip
type="number"
name="awsRootVolumeIops"
placeholder="Root Volume IOPS (optional)"
value={form.awsRootVolumeIops}
onChange={handleChange}
tooltip="The IOPS to provision for the EBS volume. Only applicable for io1, io2, or gp3 volume types."
/>

<InputWithTooltip
name="awsRootVolumeKmsKey"
placeholder="Root Volume KMS Key (optional)"
value={form.awsRootVolumeKmsKey}
onChange={handleChange}
tooltip="The AWS KMS key ID or ARN to use for EBS encryption. If not specified, the default KMS key is used."
/>
</>
);

const renderAwsNetworkConfigStep = () => (
<>
<InputWithTooltip
name="awsSubnetId"
placeholder="Subnet ID (required). Example: subnet-1234567890abcdef0"
value={form.awsSubnetId}
onChange={handleChange}
tooltip="The AWS subnet ID where worker nodes will be created. This subnet must have proper connectivity to the control plane."
/>

<InputWithTooltip
name="awsSecurityGroupId"
placeholder="Security Group ID (required). Example: sg-1234567890abcdef0"
value={form.awsSecurityGroupId}
onChange={handleChange}
tooltip="The AWS security group ID to apply to worker nodes. This security group must allow the necessary traffic for OpenShift to operate."
/>
</>
);

// Render current step content
const renderStepContent = () => {
if (step === 0) {
Expand All @@ -678,6 +834,21 @@ export default function HcpCliAssistant() {
</div>
);
}
} else if (form.platform === "aws") {
const platformStep = step - 2; // Adjust for common steps

switch (platformStep) {
case 0: return renderAwsNodeConfigStep();
case 1: return renderAwsStorageConfigStep();
case 2: return renderAwsNetworkConfigStep();
case 3: return renderCommandReviewStep();
default:
return (
<div className="p-4 bg-yellow-100 border border-yellow-400 rounded">
<p>Unknown step for the AWS platform. Please go back and try again.</p>
</div>
);
}
} else if (form.platform) {
// For any platform that is selected but not implemented
return (
Expand Down