diff --git a/web/src/components/UploadAirgapBundle.jsx b/web/src/components/UploadAirgapBundle.jsx
deleted file mode 100644
index fe9c913a3e..0000000000
--- a/web/src/components/UploadAirgapBundle.jsx
+++ /dev/null
@@ -1,693 +0,0 @@
-import * as React from "react";
-import classNames from "classnames";
-import { withRouter } from "react-router-dom";
-import { KotsPageTitle } from "@components/Head";
-import isEmpty from "lodash/isEmpty";
-import Modal from "react-modal";
-import CodeSnippet from "@src/components/shared/CodeSnippet";
-import MountAware from "@src/components/shared/MountAware";
-import AirgapUploadProgress from "@features/Dashboard/components/AirgapUploadProgress";
-import LicenseUploadProgress from "./LicenseUploadProgress";
-import AirgapRegistrySettings from "./shared/AirgapRegistrySettings";
-import { Utilities } from "../utilities/utilities";
-import { AirgapUploader } from "../utilities/airgapUploader";
-
-import "../scss/components/troubleshoot/UploadSupportBundleModal.scss";
-import "../scss/components/Login.scss";
-
-const COMMON_ERRORS = {
- "HTTP 401": "Registry credentials are invalid",
- "invalid username/password": "Registry credentials are invalid",
- "no such host": "No such host",
-};
-
-class UploadAirgapBundle extends React.Component {
- state = {
- bundleFile: {},
- fileUploading: false,
- registryDetails: {},
- preparingOnlineInstall: false,
- supportBundleCommand: undefined,
- showSupportBundleCommand: false,
- onlineInstallErrorMessage: "",
- viewOnlineInstallErrorMessage: false,
- uploadProgress: 0,
- uploadSize: 0,
- uploadResuming: false,
- };
-
- emptyHostnameErrMessage = 'Please enter a value for "Hostname" field';
-
- componentDidMount() {
- if (!this.state.airgapUploader) {
- this.getAirgapConfig();
- }
- }
-
- clearFile = () => {
- this.setState({ bundleFile: {} });
- };
-
- toggleShowRun = () => {
- this.setState({ showSupportBundleCommand: true });
- };
-
- getAirgapConfig = async () => {
- const { match } = this.props;
- const configUrl = `${process.env.API_ENDPOINT}/app/${match.params.slug}/airgap/config`;
- let simultaneousUploads = 3;
- try {
- let res = await fetch(configUrl, {
- method: "GET",
- headers: {
- "Content-Type": "application/json",
- Authorization: Utilities.getToken(),
- },
- });
- if (res.ok) {
- const response = await res.json();
- simultaneousUploads = response.simultaneousUploads;
- }
- } catch {
- // no-op
- }
-
- this.setState({
- airgapUploader: new AirgapUploader(
- false,
- match.params.slug,
- this.onDropBundle,
- simultaneousUploads
- ),
- });
- };
-
- uploadAirgapBundle = async () => {
- const { match, showRegistry } = this.props;
-
- // Reset the airgap upload state
- const resetUrl = `${process.env.API_ENDPOINT}/app/${match.params.slug}/airgap/reset`;
- try {
- await fetch(resetUrl, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: Utilities.getToken(),
- },
- });
- } catch (error) {
- console.error(error);
- this.setState({
- fileUploading: false,
- uploadProgress: 0,
- uploadSize: 0,
- uploadResuming: false,
- errorMessage:
- "An error occurred while uploading your airgap bundle. Please try again",
- });
- return;
- }
-
- this.setState({
- fileUploading: true,
- errorMessage: "",
- showSupportBundleCommand: false,
- onlineInstallErrorMessage: "",
- });
-
- if (showRegistry) {
- const { slug } = this.props.match.params;
-
- if (isEmpty(this.state.registryDetails.hostname)) {
- this.setState({
- fileUploading: false,
- uploadProgress: 0,
- uploadSize: 0,
- uploadResuming: false,
- errorMessage: this.emptyHostnameErrMessage,
- });
- return;
- }
-
- let res;
- try {
- res = await fetch(
- `${process.env.API_ENDPOINT}/app/${slug}/registry/validate`,
- {
- method: "POST",
- headers: {
- Authorization: Utilities.getToken(),
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- hostname: this.state.registryDetails.hostname,
- namespace: this.state.registryDetails.namespace,
- username: this.state.registryDetails.username,
- password: this.state.registryDetails.password,
- isReadOnly: this.state.registryDetails.isReadOnly,
- }),
- }
- );
- } catch (err) {
- this.setState({
- fileUploading: false,
- uploadProgress: 0,
- uploadSize: 0,
- uploadResuming: false,
- errorMessage: err,
- });
- return;
- }
-
- const response = await res.json();
- if (!response.success) {
- let msg =
- "An error occurred while uploading your airgap bundle. Please try again";
- if (response.error) {
- msg = response.error;
- }
- this.setState({
- fileUploading: false,
- uploadProgress: 0,
- uploadSize: 0,
- uploadResuming: false,
- errorMessage: msg,
- });
- return;
- }
- }
-
- const params = {
- registryHost: this.state.registryDetails.hostname,
- namespace: this.state.registryDetails.namespace,
- username: this.state.registryDetails.username,
- password: this.state.registryDetails.password,
- isReadOnly: this.state.registryDetails.isReadOnly,
- simultaneousUploads: this.state.simultaneousUploads,
- };
- this.state.airgapUploader.upload(
- params,
- this.onUploadProgress,
- this.onUploadError
- );
- };
-
- onUploadProgress = (progress, size, resuming = false) => {
- this.setState({
- uploadProgress: progress,
- uploadSize: size,
- uploadResuming: resuming,
- });
- };
-
- onUploadError = (message) => {
- this.setState({
- fileUploading: false,
- uploadProgress: 0,
- uploadSize: 0,
- uploadResuming: false,
- errorMessage: message || "Error uploading bundle, please try again",
- });
- };
-
- getRegistryDetails = (fields) => {
- this.setState({
- ...this.state,
- registryDetails: {
- hostname: fields.hostname,
- username: fields.username,
- password: fields.password,
- namespace: fields.namespace,
- isReadOnly: fields.isReadOnly,
- },
- });
- };
-
- onDropBundle = async (file) => {
- this.setState({
- bundleFile: file,
- onlineInstallErrorMessage: "",
- errorMessage: "",
- });
- };
-
- moveBar = (count) => {
- const elem = document.getElementById("myBar");
- const percent = count > 3 ? 96 : count * 30;
- if (elem) {
- elem.style.width = percent + "%";
- }
- };
-
- handleOnlineInstall = async () => {
- const { slug } = this.props.match.params;
-
- this.setState({
- preparingOnlineInstall: true,
- onlineInstallErrorMessage: "",
- });
-
- let resumeResult;
- fetch(`${process.env.API_ENDPOINT}/license/resume`, {
- method: "PUT",
- headers: {
- Authorization: Utilities.getToken(),
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- slug,
- }),
- })
- .then(async (result) => {
- resumeResult = await result.json();
- })
- .catch((err) => {
- this.setState({
- // TODO: use fewer flags
- fileUploading: false,
- errorMessage: err,
- preparingOnlineInstall: false,
- onlineInstallErrorMessage: err,
- });
- return;
- });
-
- let count = 0;
- const interval = setInterval(() => {
- if (this.state.onlineInstallErrorMessage.length) {
- clearInterval(interval);
- }
- count++;
- this.moveBar(count);
- if (count > 3) {
- if (!resumeResult) {
- return;
- }
-
- clearInterval(interval);
-
- if (resumeResult.error) {
- this.setState({
- // TODO: use fewer flags
- fileUploading: false,
- errorMessage: resumeResult.error,
- preparingOnlineInstall: false,
- onlineInstallErrorMessage: resumeResult.error,
- });
- return;
- }
-
- this.props.onUploadSuccess().then(() => {
- // When successful, refetch all the user's apps with onUploadSuccess
- const hasPreflight = resumeResult.hasPreflight;
- const isConfigurable = resumeResult.isConfigurable;
- if (isConfigurable) {
- this.props.history.replace(`/${slug}/config`);
- } else if (hasPreflight) {
- this.props.history.replace(`/${slug}/preflight`);
- } else {
- this.props.history.replace(`/app/${slug}`);
- }
- });
- }
- }, 1000);
- };
-
- getSupportBundleCommand = async (slug) => {
- const res = await fetch(
- `${process.env.API_ENDPOINT}/troubleshoot/app/${slug}/supportbundlecommand`,
- {
- method: "POST",
- headers: {
- Authorization: Utilities.getToken(),
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- origin: window.location.origin,
- }),
- }
- );
- if (!res.ok) {
- throw new Error(`Unexpected status code: ${res.status}`);
- }
- const response = await res.json();
- return response.command;
- };
-
- onProgressError = async (errorMessage) => {
- const { slug } = this.props.match.params;
-
- let supportBundleCommand = [];
- try {
- supportBundleCommand = await this.getSupportBundleCommand(slug);
- } catch (err) {
- console.log(err);
- }
-
- // Push this setState call to the end of the call stack
- setTimeout(() => {
- Object.entries(COMMON_ERRORS).forEach(([errorString, message]) => {
- if (errorMessage.includes(errorString)) {
- errorMessage = message;
- }
- });
-
- this.setState({
- errorMessage,
- fileUploading: false,
- uploadProgress: 0,
- uploadSize: 0,
- uploadResuming: false,
- supportBundleCommand: supportBundleCommand,
- });
- }, 0);
- };
-
- onProgressSuccess = async () => {
- const { onUploadSuccess, match } = this.props;
-
- await onUploadSuccess();
-
- const app = await this.getApp(match.params.slug);
-
- if (app?.isConfigurable) {
- this.props.history.replace(`/${app.slug}/config`);
- } else if (app?.hasPreflight) {
- this.props.history.replace(`/${app.slug}/preflight`);
- } else {
- this.props.history.replace(`/app/${app.slug}`);
- }
- };
-
- getApp = async (slug) => {
- try {
- const res = await fetch(`${process.env.API_ENDPOINT}/app/${slug}`, {
- headers: {
- Authorization: Utilities.getToken(),
- "Content-Type": "application/json",
- },
- method: "GET",
- });
- if (res.ok && res.status == 200) {
- const app = await res.json();
- return app;
- }
- } catch (err) {
- console.log(err);
- }
- return null;
- };
-
- toggleViewOnlineInstallErrorMessage = () => {
- this.setState({
- viewOnlineInstallErrorMessage: !this.state.viewOnlineInstallErrorMessage,
- });
- };
-
- toggleErrorModal = () => {
- this.setState({ displayErrorModal: !this.state.displayErrorModal });
- };
-
- render() {
- const { appName, logo, fetchingMetadata, showRegistry, appsListLength } =
- this.props;
-
- const { slug } = this.props.match.params;
-
- const {
- bundleFile,
- fileUploading,
- uploadProgress,
- uploadSize,
- uploadResuming,
- errorMessage,
- registryDetails,
- preparingOnlineInstall,
- onlineInstallErrorMessage,
- viewOnlineInstallErrorMessage,
- supportBundleCommand,
- } = this.state;
-
- const hasFile = bundleFile && !isEmpty(bundleFile);
-
- if (fileUploading) {
- return (
-
- Install in airgapped environment -
-- {showRegistry - ? `To install on an airgapped network, you will need to provide access to a Docker registry. The images ${ - applicationName?.length > 0 - ? `in ${applicationName}` - : "" - } will be retagged and pushed to the registry that you provide here.` - : `To install on an airgapped network, the images ${ - applicationName?.length > 0 - ? `in ${applicationName}` - : "" - } will be uploaded from the bundle you provide to the cluster.`} -
- {showRegistry && ( -- {bundleFile.name} -
-- Drag your airgap bundle here or{" "} - - choose a bundle to upload - -
-- This will be a .airgap file - {applicationName?.length > 0 - ? ` ${applicationName} provided` - : ""} - . Please contact your account rep if you are unable - to locate your .airgap file. -
-- Error description -
-- {onlineInstallErrorMessage} -
-- Run this command to generate a support bundle -
-+ Install in airgapped environment +
++ {showRegistry + ? `To install on an airgapped network, you will need to provide access to a Docker registry. The images ${ + applicationName?.length > 0 ? `in ${applicationName}` : "" + } will be retagged and pushed to the registry that you provide here.` + : `To install on an airgapped network, the images ${ + applicationName?.length > 0 ? `in ${applicationName}` : "" + } will be uploaded from the bundle you provide to the cluster.`} +
+ {showRegistry && ( ++ {bundleFile.name} +
++ Drag your airgap bundle here or{" "} + + choose a bundle to upload + +
++ This will be a .airgap file + {applicationName?.length > 0 + ? ` ${applicationName} provided` + : ""} + . Please contact your account rep if you are unable to + locate your .airgap file. +
++ Error description +
++ {onlineInstallErrorMessage.current} +
++ Run this command to generate a support bundle +
+