Addresses #2, more work is needed to finalize management of existing records
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@ -22,4 +22,6 @@ dist-ssr
|
|||||||
*.njsproj
|
*.njsproj
|
||||||
*.sln
|
*.sln
|
||||||
*.sw?
|
*.sw?
|
||||||
.env
|
.env
|
||||||
|
|
||||||
|
*api*/
|
10
package.json
10
package.json
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "my-vue-app",
|
"name": "kingdom",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@ -11,14 +11,14 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"envy": "^2.0.0",
|
"envy": "^2.0.0",
|
||||||
"react": "^18.3.1",
|
"react": "19",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "19",
|
||||||
"react-router-dom": "6"
|
"react-router-dom": "6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.17.0",
|
"@eslint/js": "^9.17.0",
|
||||||
"@types/react": "^18.3.18",
|
"@types/react": "19",
|
||||||
"@types/react-dom": "^18.3.5",
|
"@types/react-dom": "19",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
"eslint": "^9.17.0",
|
"eslint": "^9.17.0",
|
||||||
"eslint-plugin-react": "^7.37.2",
|
"eslint-plugin-react": "^7.37.2",
|
||||||
|
@ -35,7 +35,10 @@ input {
|
|||||||
margin: 8px 0;
|
margin: 8px 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
input[type="radio"] {
|
||||||
|
margin-top: -1px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
@ -1 +0,0 @@
|
|||||||
console.log(4)
|
|
@ -1,10 +0,0 @@
|
|||||||
import './piholeClient'
|
|
||||||
import './nginxClient'
|
|
||||||
|
|
||||||
|
|
||||||
function registerApp(props){
|
|
||||||
alert(JSON.stringify(props))
|
|
||||||
const formData = props
|
|
||||||
}
|
|
||||||
|
|
||||||
export default registerApp;
|
|
8
src/assets/orchestration.jsx
Normal file
8
src/assets/orchestration.jsx
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import pihole from './piholeClient.jsx'
|
||||||
|
// import './nginxClient'
|
||||||
|
|
||||||
|
const registerApp = (fqdn, cnameTarget, targetHost, upstreamPort, protocol) => {
|
||||||
|
console.log('Register App data: ',fqdn, cnameTarget, targetHost, upstreamPort, protocol)
|
||||||
|
pihole(fqdn, cnameTarget)
|
||||||
|
}
|
||||||
|
export default registerApp;
|
71
src/assets/piholeClient.jsx
Normal file
71
src/assets/piholeClient.jsx
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
const piholeURL = `${import.meta.env.VITE_PIHOLE_URL}/api`
|
||||||
|
|
||||||
|
const piholeAuth = async () => {
|
||||||
|
const session = await fetch(`${piholeURL}/auth`, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({ "password": import.meta.env.VITE_PIHOLE_PASSWORD })
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
return response.json()
|
||||||
|
}
|
||||||
|
else console.log(response.status) && console.log(response.statusText)
|
||||||
|
})
|
||||||
|
.then(data => data.session)
|
||||||
|
.catch(error => console.log(error))
|
||||||
|
return session
|
||||||
|
}
|
||||||
|
|
||||||
|
const getRecords = async (session) => {
|
||||||
|
const configDNS = await fetch(`${piholeURL}/config/dns/cnameRecords`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {"sid": session.sid}
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
return response.json()
|
||||||
|
}
|
||||||
|
else console.log(response.status) && console.log(response.statusText)
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
// console.log('getRecords: return data',data)
|
||||||
|
return data
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch(error => console.log(error))
|
||||||
|
return {configDNS, session}
|
||||||
|
}
|
||||||
|
|
||||||
|
const makeRecord = async (data, session, fqdn, cnameTarget) => {
|
||||||
|
const putRecord = await fetch(`${piholeURL}/config/dns/cnameRecords/${fqdn},${cnameTarget}`, {
|
||||||
|
method: "PUT",
|
||||||
|
headers: {"sid": session.sid}
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.status === 201){
|
||||||
|
// console.log(`Response: ${response.status}`)
|
||||||
|
return response.json()
|
||||||
|
}
|
||||||
|
if (!response.ok){
|
||||||
|
// console.log(`Response: ${response.status} ${response.statusText}`)
|
||||||
|
return response.json()
|
||||||
|
}
|
||||||
|
else console.log(response.status) && console.log(response.statusText)
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
if (data.error){console.log(data.error.message, data.error.hint)}
|
||||||
|
return data
|
||||||
|
})
|
||||||
|
.catch(console.error)
|
||||||
|
return putRecord
|
||||||
|
}
|
||||||
|
|
||||||
|
const pihole = (fqdn, cnameTarget) => {
|
||||||
|
const pi = piholeAuth()
|
||||||
|
pi.then(s => getRecords(s))
|
||||||
|
.then((a) => {
|
||||||
|
// console.log('pihole after getRecords', a.configDNS, a.session)
|
||||||
|
makeRecord(a.configDNS, a.session, fqdn, cnameTarget)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export default pihole
|
@ -1,72 +1,114 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import registerApp from '../assets/orchestration'
|
import registerApp from '../assets/orchestration.jsx'
|
||||||
|
|
||||||
function MyForm() {
|
function Form() {
|
||||||
const [inputs, setInputs] = useState({});
|
const envCnameTarget = import.meta.env.VITE_CNAME_TARGET_DEFAULT || ''
|
||||||
|
const [fqdn, setFQDN] = useState('');
|
||||||
|
const [cnameTarget, setCnameTarget] = useState(envCnameTarget);
|
||||||
|
const [targetHost, setTargetHost] = useState('');
|
||||||
|
const [upstreamPort, setUpstreamPort] = useState('');
|
||||||
|
const [protocol, setProtocol] = useState('http');
|
||||||
|
|
||||||
const handleChange = (event) => {
|
|
||||||
const name = event.target.name;
|
|
||||||
const value = event.target.value;
|
|
||||||
setInputs(values => ({ ...values, [name]: value }))
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<form className='card'>
|
<form className='card' id="create-service" action={
|
||||||
|
() => registerApp(fqdn, cnameTarget, targetHost, upstreamPort, protocol)}>
|
||||||
|
|
||||||
<h4>DNS</h4>
|
<h4>DNS</h4>
|
||||||
<label>FQDN
|
<label>
|
||||||
<input type="text" name="fqdn" value={inputs.fqdn} onChange={handleChange} placeholder='Target DNS name.' required autoFocus/>
|
FQDN
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="fqdn"
|
||||||
|
value={fqdn}
|
||||||
|
onChange={e => setFQDN(e.target.value)}
|
||||||
|
placeholder='Target DNS name.'
|
||||||
|
required
|
||||||
|
autoFocus />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<label>CNAME Target
|
<label>
|
||||||
<input type="text" name="cname_target" value={inputs.cname_target} onChange={handleChange} placeholder='cygnus.int.jonb.io' required/>
|
CNAME Target
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="cnameTarget"
|
||||||
|
value={cnameTarget}
|
||||||
|
onChange={e => setCnameTarget(e.target.value)}
|
||||||
|
placeholder='Backend server DNS CNAME'
|
||||||
|
required />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<h4>Reverse Proxy</h4>
|
<h4>Reverse Proxy</h4>
|
||||||
|
|
||||||
<label>FQDN
|
<label>
|
||||||
<input type="text" value={inputs.fqdn} onChange={handleChange} disabled placeholder='Automatically filled, Target DNS name'/>
|
FQDN
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={fqdn}
|
||||||
|
disabled
|
||||||
|
placeholder='Target DNS name' />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<label>Target Host
|
<label>
|
||||||
<input type="text" name="target_host" value={inputs.target_host} onChange={handleChange} placeholder='Network host Domain or IP' required/>
|
Target Host
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="targetHost"
|
||||||
|
value={targetHost}
|
||||||
|
onChange={e => setTargetHost(e.target.value)}
|
||||||
|
placeholder='Network host Domain or IP'
|
||||||
|
required />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<label>Upstream Port
|
<label>
|
||||||
<input type="number" name="upstream_port" value={inputs.upstream_port} onChange={handleChange} placeholder='Port the target service is listening on.' required/>
|
Upstream Port
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="upstreamPort"
|
||||||
|
value={upstreamPort}
|
||||||
|
onChange={e => setUpstreamPort(e.target.value)}
|
||||||
|
placeholder='Port the target service is listening on.'
|
||||||
|
required />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<label>Protocol
|
<select
|
||||||
<select name="protocol" value={inputs.protocol || "http"} onChange={handleChange}>
|
name="protocol"
|
||||||
<option value="http" selected>HTTP</option>
|
value={protocol}
|
||||||
<option value="https">HTTPS</option>
|
onChange={e => setProtocol(e.target.value)}>
|
||||||
</select>
|
<option value="http">http</option>
|
||||||
</label>
|
<option value="https">https</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<button className="button" type="submit" onChange={handleChange} onClick={() => registerApp({inputs})}>Submit</button>
|
<button
|
||||||
|
className="button"
|
||||||
|
type="submit">
|
||||||
|
Create
|
||||||
|
</button>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function Home() {
|
function Home() {
|
||||||
return (<><h2>Deploy New App</h2>
|
return (
|
||||||
<MyForm />
|
<>
|
||||||
</>
|
<h2>Deploy New App</h2>
|
||||||
|
<Form />
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
55
yarn.lock
55
yarn.lock
@ -562,22 +562,16 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
|
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
|
||||||
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
|
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
|
||||||
|
|
||||||
"@types/prop-types@*":
|
"@types/react-dom@19":
|
||||||
version "15.7.14"
|
version "19.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.14.tgz#1433419d73b2a7ebfc6918dcefd2ec0d5cd698f2"
|
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.1.6.tgz#4af629da0e9f9c0f506fc4d1caa610399c595d64"
|
||||||
integrity sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==
|
integrity sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==
|
||||||
|
|
||||||
"@types/react-dom@^18.3.5":
|
"@types/react@19":
|
||||||
version "18.3.7"
|
version "19.1.8"
|
||||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.7.tgz#b89ddf2cd83b4feafcc4e2ea41afdfb95a0d194f"
|
resolved "https://registry.yarnpkg.com/@types/react/-/react-19.1.8.tgz#ff8395f2afb764597265ced15f8dddb0720ae1c3"
|
||||||
integrity sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==
|
integrity sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==
|
||||||
|
|
||||||
"@types/react@^18.3.18":
|
|
||||||
version "18.3.20"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.20.tgz#b0dccda9d2f1bc24d2a04b1d0cb5d0b9a3576ad3"
|
|
||||||
integrity sha512-IPaCZN7PShZK/3t6Q87pfTkRm6oLTd4vztyoj+cbHUF1g3FfVb2tFIL79uCRKEfv16AhqDMBywP2VW3KIZUvcg==
|
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/prop-types" "*"
|
|
||||||
csstype "^3.0.2"
|
csstype "^3.0.2"
|
||||||
|
|
||||||
"@vitejs/plugin-react@^4.3.4":
|
"@vitejs/plugin-react@^4.3.4":
|
||||||
@ -1709,7 +1703,7 @@ lodash.merge@^4.6.2:
|
|||||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||||
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
||||||
|
|
||||||
loose-envify@^1.1.0, loose-envify@^1.4.0:
|
loose-envify@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||||
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||||
@ -1934,13 +1928,12 @@ quick-lru@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8"
|
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8"
|
||||||
integrity sha512-tRS7sTgyxMXtLum8L65daJnHUhfDUgboRdcWW2bR9vBfrj2+O5HSMbQOJfJJjIVSPFqbBCF37FpwWXGitDc5tA==
|
integrity sha512-tRS7sTgyxMXtLum8L65daJnHUhfDUgboRdcWW2bR9vBfrj2+O5HSMbQOJfJJjIVSPFqbBCF37FpwWXGitDc5tA==
|
||||||
|
|
||||||
react-dom@^18.3.1:
|
react-dom@19:
|
||||||
version "18.3.1"
|
version "19.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4"
|
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.1.0.tgz#133558deca37fa1d682708df8904b25186793623"
|
||||||
integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==
|
integrity sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify "^1.1.0"
|
scheduler "^0.26.0"
|
||||||
scheduler "^0.23.2"
|
|
||||||
|
|
||||||
react-is@^16.13.1:
|
react-is@^16.13.1:
|
||||||
version "16.13.1"
|
version "16.13.1"
|
||||||
@ -1967,12 +1960,10 @@ react-router@6.30.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@remix-run/router" "1.23.0"
|
"@remix-run/router" "1.23.0"
|
||||||
|
|
||||||
react@^18.3.1:
|
react@19:
|
||||||
version "18.3.1"
|
version "19.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891"
|
resolved "https://registry.yarnpkg.com/react/-/react-19.1.0.tgz#926864b6c48da7627f004795d6cce50e90793b75"
|
||||||
integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
|
integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==
|
||||||
dependencies:
|
|
||||||
loose-envify "^1.1.0"
|
|
||||||
|
|
||||||
reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9:
|
reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9:
|
||||||
version "1.0.10"
|
version "1.0.10"
|
||||||
@ -2071,12 +2062,10 @@ safe-regex-test@^1.1.0:
|
|||||||
es-errors "^1.3.0"
|
es-errors "^1.3.0"
|
||||||
is-regex "^1.2.1"
|
is-regex "^1.2.1"
|
||||||
|
|
||||||
scheduler@^0.23.2:
|
scheduler@^0.26.0:
|
||||||
version "0.23.2"
|
version "0.26.0"
|
||||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3"
|
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.26.0.tgz#4ce8a8c2a2095f13ea11bf9a445be50c555d6337"
|
||||||
integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==
|
integrity sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==
|
||||||
dependencies:
|
|
||||||
loose-envify "^1.1.0"
|
|
||||||
|
|
||||||
semver@^6.3.1:
|
semver@^6.3.1:
|
||||||
version "6.3.1"
|
version "6.3.1"
|
||||||
|
Reference in New Issue
Block a user