Skip to content

Commit

Permalink
Feature: Port-forward command (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
dzsak authored Jan 13, 2024
1 parent 27bc31f commit e5126fe
Showing 1 changed file with 70 additions and 5 deletions.
75 changes: 70 additions & 5 deletions web/src/Service.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useState, useEffect } from 'react';
import Timeline from './Timeline';
import { RevisionWidget, ReadyWidget } from './FluxState';
import jp from 'jsonpath';
import { XMarkIcon } from '@heroicons/react/24/outline';
Expand All @@ -23,6 +22,22 @@ function Service(props) {
const configMapWidgets = configMaps(service.pods, service.svc.metadata.namespace, capacitorClient)
const secretWidgets = secrets(service.pods, service.svc.metadata.namespace, capacitorClient)

const svcPort = service.svc.spec.ports[0].port
let hostPort = "<host-port>"
if (svcPort) {
if (svcPort <= 99) {
hostPort = "100" + svcPort
} else if (svcPort <= 999) {
hostPort = "10" + svcPort
} else {
hostPort = svcPort
}

if (hostPort === "10080") { // Connections to HTTP, HTTPS or FTP servers on port 10080 will fail. This is a mitigation for the NAT Slipstream 2.0 attack.
hostPort = "10081"
}
}

return (
<>
<div className="w-full flex items-center justify-between space-x-6 bg-white pb-6 rounded-lg border border-neutral-300 shadow-lg">
Expand Down Expand Up @@ -144,10 +159,12 @@ function Service(props) {
<div className="text-neutral-900 text-sm">
<div className="relative">
{service.svc.metadata.name}.{service.svc.metadata.namespace}.svc.cluster.local
<button
className="absolute right-0 bg-transparent hover:bg-neutral-100 font-medium text-sm text-neutral-700 py-1 px-4 border border-neutral-300 rounded">
Port-forward command
</button>
<div className='absolute right-0 top-0'>
<CopyBtn
title='Port-forward command'
textToCopy={`kubectl port-forward deploy/${deployment.metadata.name} -n ${deployment.metadata.namespace} ${hostPort}:${svcPort}`}
/>
</div>
</div>
{service.ingresses ? service.ingresses.map((ingress) =>
<p key={`${ingress.namespace}/${ingress.name}`}>
Expand All @@ -163,6 +180,20 @@ function Service(props) {
</p>
) : null
}
{svcPort &&
<>
<a href={'http://127.0.0.1:' + hostPort} target="_blank" rel="noopener noreferrer">http://127.0.0.1:{hostPort}
<svg xmlns="http://www.w3.org/2000/svg"
className="inline fill-current text-gray-500 hover:text-gray-700 mr-1 h-4 w-4"
viewBox="0 0 24 24">
<path d="M0 0h24v24H0z" fill="none" />
<path
d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z" />
</svg>
</a>
(port-forward)
</>
}
</div>
</div>
}
Expand Down Expand Up @@ -377,3 +408,37 @@ const SkeletonLoader = () => {
</div>
)
}

function CopyBtn({ title, textToCopy }) {
const [copied, setCopied] = useState(false);

const copyToClipboard = () => {
navigator.clipboard.writeText(textToCopy).then(
() => {
setCopied(true);
// changing back to default state after 2 seconds.
setTimeout(() => {
setCopied(false);
}, 2000);
},
(err) => {
console.log("failed to copy", err.mesage);
}
);
};

return (
<div>
{copied &&
<span className="absolute select-none right-1/4 -top-8 z-10 py-1 px-2 bg-gray-900 text-xs font-medium text-white rounded-lg shadow-sm dark:bg-slate-700">
Copied
</span>
}
<button
onClick={copyToClipboard}
className="bg-transparent hover:bg-neutral-100 font-medium text-sm text-neutral-700 py-1 px-4 border border-neutral-300 rounded">
{title}
</button>
</div>
);
}

0 comments on commit e5126fe

Please sign in to comment.