Skip to content

Commit

Permalink
Merge pull request #9 from tanmoysrt/ingress_management
Browse files Browse the repository at this point in the history
Ingress management
  • Loading branch information
tanmoysrt authored Aug 13, 2023
2 parents f5ca3b9 + b86a03b commit 86f767a
Show file tree
Hide file tree
Showing 7 changed files with 608 additions and 6 deletions.
222 changes: 222 additions & 0 deletions src/components/addIngressRulesModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
/* eslint-disable react/prop-types */
import {
Box,
Button,
Center,
FormControl,
FormErrorMessage,
FormHelperText,
FormLabel,
Icon,
Input,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
Select,
} from "@chakra-ui/react";
import { ArrowDownIcon } from "@primer/octicons-react";
import { useContext, useEffect, useRef, useState } from "react";
import ControllerContext from "../context/controller/ControllerContext";

export default function AddIngressRulesModal({ addRule, onClose, isOpen }) {
const controllerContext = useContext(ControllerContext);
const [isAdding, setIsAdding] = useState(false);
const [domains, setDomains] = useState([]);
const [services, setServices] = useState([]);
const [protocol, setProtocol] = useState("http");
const [restrictedPorts, setRestrictedPorts] = useState([]);
const [ingressPortInvalid, setIngressPortInvalid] = useState(false);
const protocolFieldRef = useRef();
const domainFieldRef = useRef();
const ingressPortFieldRef = useRef();
const serviceNameFieldRef = useRef();
const servicePortFieldRef = useRef();

const handleSubmission = async () => {
setIsAdding(true);
await addRule({
protocol: protocolFieldRef.current.value,
domain_name: domainFieldRef.current.value,
port: ingressPortFieldRef.current
? ingressPortFieldRef.current.value
: "",
service_name: serviceNameFieldRef.current.value,
service_port: servicePortFieldRef.current.value,
});
setIsAdding(false);
};

const fetchDomains = async () => {
const res = await controllerContext.domains.fetchNames();
if (res.status) {
setDomains(res.data);
} else {
console.log(res.message);
}
};

const fetchServiceNames = async () => {
const res = await controllerContext.applications.fetchNames();
if (res.status) {
setServices(res.data);
} else {
console.log(res.message);
}
};

const fetchRestrictedPorts = async () => {
const res = await controllerContext.ingress_rules.fetchRestrictedPorts();
if (res.status) {
let ports = res.data;
// remove port 80 from list
ports = ports.filter((port) => port !== 80);
setRestrictedPorts(ports);
} else {
console.log(res.message);
}
};

const validateIngressPort = () => {
if (ingressPortFieldRef.current) {
const port = ingressPortFieldRef.current.value;
if (protocolFieldRef.current.value === "https") {
setIngressPortInvalid(false);
} else if (restrictedPorts.includes(parseInt(port))) {
setIngressPortInvalid(true);
} else {
setIngressPortInvalid(false);
}
}
};

useEffect(() => {
// reset form
if (domainFieldRef.current) {
protocolFieldRef.current.value = "http";
domainFieldRef.current.value = "";
serviceNameFieldRef.current.value = "";
servicePortFieldRef.current.value = "";
if (ingressPortFieldRef.current) ingressPortFieldRef.current.value = "80";
}
fetchDomains();
fetchServiceNames();
fetchRestrictedPorts();
setIngressPortInvalid(false);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isOpen]);

return (
<Modal isOpen={isOpen} onClose={onClose} closeOnOverlayClick={false}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Ingress Rule</ModalHeader>
<ModalCloseButton />
<ModalBody pb={6}>
<Box display="grid" gridTemplateColumns="1fr 3fr" gap="5" pb={4}>
<FormControl>
<FormLabel>Protocol</FormLabel>
<Select
defaultValue="http"
onChange={(e) => {
setProtocol(e.target.value);
if (e.target.value === "http") {
ingressPortFieldRef.current.value = "80";
}
}}
ref={protocolFieldRef}
>
<option value="http">http</option>
<option value="https">https</option>
<option value="tcp">tcp</option>
</Select>
</FormControl>

<FormControl>
<FormLabel>Domain</FormLabel>
<Select defaultValue="dummy" ref={domainFieldRef}>
<option disabled value="dummy">
Select Domain
</option>
{domains.map((domain) => (
<option key={domain} value={domain}>
{domain}
</option>
))}
</Select>
</FormControl>
</Box>

<FormControl
hidden={protocol === "https"}
isInvalid={ingressPortInvalid}
>
<FormLabel>Enter Port</FormLabel>
<Input
placeholder="Enter Ingress Port"
ref={ingressPortFieldRef}
defaultValue={80}
onInput={validateIngressPort}
/>
{ingressPortInvalid ? (
<FormErrorMessage>
{restrictedPorts.length > 0
? `Port (${restrictedPorts.join(", ")}) are restricted`
: ""}
</FormErrorMessage>
) : (
<FormHelperText>
{restrictedPorts.length > 0
? `Port (${restrictedPorts.join(", ")}) are restricted`
: ""}
</FormHelperText>
)}
</FormControl>

<Center pt="3">
<Icon as={ArrowDownIcon} fontSize="4xl" color="brand.800"></Icon>
</Center>

<Box display="grid" gridTemplateColumns="3fr 1fr" gap="5">
<FormControl>
<FormLabel>Service Name</FormLabel>
<Select defaultValue="dummy" ref={serviceNameFieldRef}>
<option disabled value="dummy">
Select Service
</option>
{services.map((service) => (
<option key={service} value={service}>
{service}
</option>
))}
</Select>
</FormControl>

<FormControl>
<FormLabel>Port</FormLabel>
<Input placeholder="port" ref={servicePortFieldRef} />
</FormControl>
</Box>
</ModalBody>

<ModalFooter>
<Button
colorScheme="brand"
mr={3}
onClick={handleSubmission}
isLoading={isAdding}
isDisabled={isAdding}
>
Create
</Button>
<Button onClick={onClose} isDisabled={isAdding}>
Cancel
</Button>
</ModalFooter>
</ModalContent>
</Modal>
);
}
3 changes: 3 additions & 0 deletions src/config/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ export default {
AUTH_VERIFY: '/auth/verify',
AUTH_LOGOUT: '/auth/logout',
REDIRECT_RULES: '/mapping/redirects',
INGRESS_RULES: '/mapping/ingresses',
RESTRICTED_PORTS: '/mapping/ingresses/restricted-ports',
DOMAINS: '/domains',
DOMAIN_NAMES: '/domains/shortlist',
GIT_CREDENTIALS: '/git/credentials',
VOLUMES: '/volumes',
SERVICE_NAMES: '/applications/servicenames'
}
1 change: 1 addition & 0 deletions src/config/tag_color.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export default {
"applied": "green",
"pending": "yellow",
"delete_pending": "red",
"failed": "red",
}
4 changes: 4 additions & 0 deletions src/context/controller/ControllerState.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
/* eslint-disable react/prop-types */

import ControllerContext from "./ControllerContext";
import ApplicationController from "./_applicationController";
import DomainController from "./_domainController";
import GitCredentialsController from "./_gitCredentialsController";
import IngressRulesController from "./_ingressRulesController";
import RedirectRulesController from "./_redirectRulesController";
import VolumeController from "./_volumeController";

const ControllerState = (props) => {
const controllers = {
"redirect_rules": new RedirectRulesController(),
"ingress_rules": new IngressRulesController(),
"domains": new DomainController(),
"git_credentials": new GitCredentialsController(),
"volumes": new VolumeController(),
"applications": new ApplicationController(),
}

// Return
Expand Down
27 changes: 27 additions & 0 deletions src/context/controller/_applicationController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import axios from "axios"
import route from "../../config/route"

export default class ApplicationController {

// fetch service names
async fetchNames(){
try {
const res = await axios({
method: 'get',
url: route.SERVICE_NAMES
})
return {
status: true,
message: 'Success',
data: res.data
}
} catch (error) {
let message = error.response.data.message || "Failed to fetch service names"
return {
status: false,
message: message,
data: []
}
}
}
}
Loading

0 comments on commit 86f767a

Please sign in to comment.