Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI Secret restore #854

Merged
4 changes: 2 additions & 2 deletions docs/contributor/09-10-ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Follow the steps below to run BTP Manager with UI:
```
3. Set the **IMG** environment variable to the image of BTP Manager with UI.
```shell
export IMG=europe-docker.pkg.dev/kyma-project/dev/btp-manager:PR-853
export IMG=europe-docker.pkg.dev/kyma-project/dev/btp-manager:PR-854
```
4. Run `deploy` makefile rule to deploy BTP Manager with UI.
```shell
Expand All @@ -42,7 +42,7 @@ Follow the steps below to run BTP Manager with UI:
```
If you encounter the following error during Pod creation due to Warden's admission webhook:
```
Error creating: admission webhook "validation.webhook.warden.kyma-project.io" denied the request: Pod images europe-docker.pkg.dev/kyma-project/dev/btp-manager:PR-853 validation failed
Error creating: admission webhook "validation.webhook.warden.kyma-project.io" denied the request: Pod images europe-docker.pkg.dev/kyma-project/dev/btp-manager:PR-854 validation failed
```
you must scale the BTP Manager deployment to 0 replicas, delete the webhook, and then scale the deployment back to 1 replica.
```shell
Expand Down
4 changes: 2 additions & 2 deletions ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "smuiii",
"version": "0.1.0",
"name": "btp-manager-ui",
"version": "0.0.1",
"private": true,
"dependencies": {
"@reduxjs/toolkit": "^2.2.3",
Expand Down
188 changes: 143 additions & 45 deletions ui/src/components/CreateBindingForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import api from "../shared/api";
import axios from "axios";
import StatusMessage from "./StatusMessage";
import '@ui5/webcomponents/dist/features/InputElementsFormSupport.js';
import { generateRandom5CharString } from "../shared/common";

function CreateBindingForm(props: any) {
const [loading, setLoading] = useState(true);
Expand All @@ -17,6 +18,20 @@ function CreateBindingForm(props: any) {
const [createdBinding, setCreatedBinding] = useState<ServiceInstanceBinding>(new ServiceInstanceBinding());
const [success, setSuccess] = useState("");

function resetCreateBindingForm(response: any) {
const suffix = "-" + generateRandom5CharString()

const binding = new ServiceInstanceBinding()
binding.name = props.instanceName
binding.secret_name = props.instanceName + suffix
binding.secret_namespace = "default"

setCreatedBinding(binding);
setError(undefined);
setLoading(false);
return response;
}

const handleCreate = (e: any): boolean => {
setLoading(true)
e.preventDefault();
Expand All @@ -27,48 +42,71 @@ function CreateBindingForm(props: any) {
return false;
}

createdBinding.service_instance_id = props.instanceId ?? ""

axios
.post<ServiceInstanceBinding>(api("service-bindings"), {
name: createdBinding.name,
service_instance_id: createdBinding.service_instance_id,
secret_name: createdBinding.secret_name,
secret_namespace: createdBinding.secret_namespace
}, {
params:
{
sm_secret_name: props.secret!!.name,
sm_secret_namespace: props.secret!!.namespace
}
})
.then((response) => {

// propagate the created binding
props.onCreate(response.data);

// reset binding
const binding = new ServiceInstanceBinding()
binding.name = props.instanceName
binding.secret_name = props.instanceName
binding.secret_namespace = "default"

setSuccess("Item with id " + response.data.name + " created.");
setCreatedBinding(binding);
setError(undefined);
setLoading(false);
})
.catch((error: ApiError) => {
setLoading(false);
setError(error);
setSuccess("");
});
setLoading(true)
axios
.post<ServiceInstanceBinding>(api("service-bindings"), {
name: createdBinding.name,
service_instance_id: props.instanceId ?? "",
secret_name: createdBinding.secret_name,
secret_namespace: createdBinding.secret_namespace
}, {
params:
{
sm_secret_name: props.secret!!.name,
sm_secret_namespace: props.secret!!.namespace
}
})
.then(resetCreateBindingForm)
.then((response) => {
props.onCreate(response.data);
setSuccess("Item with id " + response.data.name + " created.");
})
.catch((error: ApiError) => {
setLoading(false);
setError(error);
setSuccess("");
});

e.preventDefault();
e.stopPropagation();
return false;
}

const handleSecretRestore = (e: any): boolean => {
e.preventDefault();
if (e.nativeEvent.submitter.localName === "ui5-multi-input") {
e.preventDefault()
return false;
}

setLoading(true)
axios
.put(api("service-bindings") + "/" + createdBinding.id, {
name: createdBinding.name,
service_instance_id: props.instanceId ?? "",
secret_name: createdBinding.secret_name,
secret_namespace: createdBinding.secret_namespace
}, {
params: {
sm_secret_name: props.secret.name,
sm_secret_namespace: props.secret.namespace
}
})
.then(resetCreateBindingForm)
.then((response) => {
props.onSecretRestore(createdBinding);
setSuccess("Item with id " + response.data.name + " updated.");
})
.catch((error: ApiError) => {
setLoading(false);
setError(error);
setSuccess("");
});

e.preventDefault();
return false;
}

useEffect(() => {
setLoading(true)
if (!Ok(props.instanceId)) {
Expand All @@ -83,16 +121,24 @@ function CreateBindingForm(props: any) {
return;
}

setLoading(false);
setError(undefined);
const suffix = "-" + generateRandom5CharString()
const currentBinding = new ServiceInstanceBinding()
if (props.buttonPressed) {
currentBinding.id = props.binding.id
currentBinding.name = props.binding.name
currentBinding.secret_name = props.binding.name + suffix
currentBinding.secret_namespace = "default"
setCreatedBinding(currentBinding)
} else {
currentBinding.name = props.instanceName
currentBinding.secret_name = props.instanceName + suffix
currentBinding.secret_namespace = "default"
setCreatedBinding(currentBinding)
}

setLoading(false)
setError(undefined)

createdBinding.name = props.instanceName
createdBinding.secret_name = props.instanceName
createdBinding.secret_namespace = "default"
setCreatedBinding(createdBinding)

}, [createdBinding, props.instanceId, props.instanceName, props.onCreate, props.secret]);
}, [props.instanceId, props.instanceName, props.onCreate, props.secret, props.binding, props.buttonPressed]);

const renderData = () => {

Expand All @@ -104,6 +150,58 @@ function CreateBindingForm(props: any) {
/>
}

if (props.buttonPressed) {
return (
<ui5.Form
onSubmit={handleSecretRestore}>
<ui5.FormItem>
<StatusMessage error={error ?? undefined} success={success} />
</ui5.FormItem>
<ui5.FormItem label={<ui5.Label required>Name</ui5.Label>}>
<ui5.Input
style={{ width: "100%" }}
required
value={createdBinding?.name ?? ''}
disabled={true}
onChange={(e) => {
createdBinding!!.name = e.target.value
setCreatedBinding(createdBinding)
}}
/>
</ui5.FormItem>

<ui5.FormItem label={<ui5.Label required>Secret Name</ui5.Label>}>
<ui5.Input
style={{ width: "100%" }}
required
value={createdBinding?.secret_name ?? ''}
onChange={(e) => { // defaulted to service instance name
createdBinding!!.secret_name = e.target.value
setCreatedBinding(createdBinding)
}}
/>
</ui5.FormItem>

<ui5.FormItem label={<ui5.Label required>Secret Namespace</ui5.Label>}>
<ui5.Input
style={{ width: "100%" }}
required // default to "default"
value={createdBinding?.secret_namespace ?? ''}
onChange={(e) => {
createdBinding!!.secret_namespace = e.target.value
setCreatedBinding(createdBinding)
}}
/>
</ui5.FormItem>

<ui5.FormItem>
<ui5.Button type={ui5.ButtonType.Submit}>Submit</ui5.Button>
</ui5.FormItem>
</ui5.Form>

)
}

return (
<ui5.Form
onSubmit={handleCreate}>
Expand Down
Loading
Loading