touch ups

This commit is contained in:
2025-05-28 13:59:28 +09:30
parent 84d14e75a1
commit c06df5cb74
4 changed files with 107 additions and 141 deletions
+68 -140
View File
@@ -9,14 +9,10 @@ def render_list():
st.header("Container Workload Management")
# Initialize session state flags for pod deletion
if 'pod_delete_all_confirmation_shown' not in st.session_state:
st.session_state.pod_delete_all_confirmation_shown = False
if 'pod_delete_all_confirmed' not in st.session_state:
st.session_state.pod_delete_all_confirmed = False
if 'pod_delete_confirmation_shown' not in st.session_state:
st.session_state.pod_delete_confirmation_shown = False
if 'pod_delete_confirmed' not in st.session_state:
st.session_state.pod_delete_confirmed = False
for flag in ['pod_delete_all_confirmation_shown', 'pod_delete_all_confirmed',
'pod_delete_confirmation_shown', 'pod_delete_confirmed']:
if flag not in st.session_state:
st.session_state[flag] = False
# Fetch VDCs
vdcs = st.session_state.client.get_virtual_data_centers()
@@ -26,134 +22,80 @@ def render_list():
# Create Container Workload Form
with st.expander("Create New Container Workload"):
# The form only contains form-specific widgets
with st.form("create_container"):
# Dropdown for VDC selection
selected_vdc_name_create = st.selectbox("VDC", list(vdc_options.keys()))
container_name = st.text_input("Container Name", value="my-container")
# Suggestions for common images
docker_image_options = ["nginx", "traefik/whoami:latest", "whoami81","noisy_container"]
docker_image = st.selectbox(
"Docker Image",
options=docker_image_options + ["Custom..."],
index=0
)
# Docker image selection
docker_image_options = ["nginx", "traefik/whoami:latest", "whoami81", "noisy_container", "joke_container"]
selected_predefined = st.selectbox("Choose a common image", [""] + docker_image_options)
custom_input = st.text_input("Or enter custom Docker image", value="")
# If 'Custom...' is selected, let the user input their own image
if docker_image == "Custom...":
docker_image = st.text_input("Custom Docker Image", value="")
docker_image = custom_input.strip() if custom_input.strip() else selected_predefined.strip()
# Port mappings (multiple)
# Port mappings
st.markdown("**Port Mappings**")
# Initialize port mappings in session state if not exists
if 'port_mappings' not in st.session_state:
st.session_state.port_mappings = [{
'internal': None,
'external': None,
'use_dns': True,
'protocol': 'tcp'
'internal': None, 'external': None,
'use_dns': True, 'protocol': 'tcp'
}]
# Display each port mapping
for i, mapping in enumerate(st.session_state.port_mappings):
with st.container():
cols = st.columns([2, 2, 2, 1, 1])
cols = st.columns([2, 2, 2, 1])
with cols[0]:
internal_port = st.number_input(
"Internal Port",
min_value=1,
max_value=65535,
step=1,
value=mapping['internal'],
key=f"internal_{i}"
)
internal_port = st.number_input("Internal Port", 1, 65535, value=mapping['internal'] or 1, key=f"internal_{i}")
with cols[1]:
external_port = st.number_input(
"External Port",
min_value=1,
max_value=65535,
step=1,
value=mapping['external'],
key=f"external_{i}"
)
external_port = st.number_input("External Port", 1, 65535, value=mapping['external'] or 1, key=f"external_{i}")
with cols[2]:
protocol = st.selectbox(
"Protocol",
["tcp", "udp"],
index=0 if mapping['protocol'] == 'tcp' else 1,
key=f"protocol_{i}"
)
protocol = st.selectbox("Protocol", ["tcp", "udp"], index=0 if mapping['protocol'] == 'tcp' else 1, key=f"protocol_{i}")
with cols[3]:
use_dns = st.checkbox(
"Use DNS",
value=mapping['use_dns'],
key=f"use_dns_{i}"
)
# with cols[4]:
# # Only show remove button for additional port mappings
# if i > 0:
# if st.button("❌", key=f"remove_{i}"):
# st.session_state.port_mappings.pop(i)
# st.rerun()
use_dns = st.checkbox("Use DNS", value=mapping['use_dns'], key=f"use_dns_{i}")
# Form submit button for creating the container
submit = st.form_submit_button("Create Container Workload")
if submit and selected_vdc_name_create and container_name:
vdc_id = vdc_options[selected_vdc_name_create]
if submit:
if not docker_image:
st.warning("Please specify a Docker image.")
else:
vdc_id = vdc_options[selected_vdc_name_create]
port_mappings = []
for i in range(len(st.session_state.port_mappings)):
internal = st.session_state.get(f"internal_{i}")
external = st.session_state.get(f"external_{i}")
protocol = st.session_state.get(f"protocol_{i}")
use_dns = st.session_state.get(f"use_dns_{i}")
if internal and external:
port_mappings.append({
"internal": int(internal),
"external": int(external),
"protocol": protocol,
"use_dns": use_dns
})
container_payload = {
"docker_image": docker_image,
"container_name": container_name,
"networks": "bridge"
}
if port_mappings:
container_payload["ports"] = port_mappings
payload = {
"vdc": vdc_id,
"containers": [container_payload]
}
result = st.session_state.client.create_container(payload)
if result:
st.success("Container workload created successfully!")
st.session_state.port_mappings = [{
'internal': None, 'external': None,
'use_dns': True, 'protocol': 'tcp'
}]
st.rerun()
container_payload = {
"docker_image": docker_image,
"container_name": container_name,
"networks": "bridge", # Default network
}
# Prepare port mappings from session state
port_mappings = []
for i in range(len(st.session_state.port_mappings)):
internal = st.session_state.get(f"internal_{i}")
external = st.session_state.get(f"external_{i}")
protocol = st.session_state.get(f"protocol_{i}")
use_dns = st.session_state.get(f"use_dns_{i}")
if internal and external: # Only add if both ports are specified
port_mappings.append({
"internal": int(internal),
"external": int(external),
"protocol": protocol,
"use_dns": use_dns
})
if port_mappings:
container_payload["ports"] = port_mappings
payload = {
"vdc": vdc_id,
"containers": [container_payload]
}
result = st.session_state.client.create_container(payload)
if result:
st.success("Container workload created successfully!")
# Clear port mappings after successful creation
st.session_state.port_mappings = [{
'internal': None,
'external': None,
'use_dns': True,
'protocol': 'tcp'
}]
st.rerun()
# The button to add a new port mapping is now placed outside the form
if st.button("➕ Add Another Port Mapping"):
st.session_state.port_mappings.append({
'internal': None,
'external': None,
'use_dns': True,
'protocol': 'tcp'
'internal': None, 'external': None,
'use_dns': True, 'protocol': 'tcp'
})
st.rerun()
@@ -162,24 +104,22 @@ def render_list():
pods = st.session_state.client.get_container_pods()
if pods:
# Filter by selected VDC
selected_vdc_id = vdc_options[selected_vdc_name]
filtered_pods = [pod for pod in pods if pod['vdc_id'] == selected_vdc_id]
# Delete All Pods
if not st.session_state.pod_delete_all_confirmation_shown:
if st.button("Delete All Pods", key="delete_all_pods", type="primary", help="This will delete all visible pods"):
if st.button("Delete All Pods", key="delete_all_pods", type="primary"):
st.session_state.pod_delete_all_confirmation_shown = True
st.rerun()
if st.session_state.pod_delete_all_confirmation_shown and not st.session_state.pod_delete_all_confirmed:
st.warning("Are you sure you want to delete all pods? This action cannot be undone.")
confirm_col1, confirm_col2 = st.columns([1, 1])
with confirm_col1:
st.warning("Are you sure you want to delete all pods?")
col1, col2 = st.columns([1, 1])
with col1:
if st.button("Yes, Delete All Pods", key="confirm_delete_all_pods"):
st.session_state.pod_delete_all_confirmed = True
st.rerun()
with confirm_col2:
with col2:
if st.button("Cancel", key="cancel_delete_all_pods"):
st.session_state.pod_delete_all_confirmation_shown = False
st.rerun()
@@ -195,37 +135,26 @@ def render_list():
st.session_state.pod_delete_all_confirmed = False
st.rerun()
# Render Pods nicely
for pod in filtered_pods:
with st.expander(f"🛰️ Pod: {pod['pod_name']} (ID: {pod['pod_id']})", expanded=False):
with st.expander(f"🛰️ Pod: {pod['pod_name']} (ID: {pod['pod_id']})"):
st.markdown(f"**Virtual Data Center ID:** `{pod['vdc_id']}`")
st.markdown(f"**Region ID:** `{pod.get('region_id', 'N/A')}`")
st.markdown(f"**NSController ID:** `{pod['nscontroller_workload_id']}`")
# Port Forwardings
if 'port_forwardings' in pod and pod['port_forwardings']:
if pod.get('port_forwardings'):
st.markdown("🔁 **Port Forwarding:**")
for pf in pod['port_forwardings']:
dns_status = "🌐 DNS" if pf.get('dns_record_id') else "🚫 No DNS"
cols = st.columns([1, 3, 2])
with cols[0]:
st.markdown(f"**{pf['protocol'].upper()}**")
with cols[1]:
st.text(f"{pf['external_port']} → {pf['internal_port']}")
with cols[2]:
st.text(dns_status)
if pf.get('dns_record_hostname'):
st.page_link(f"http://{pf['dns_record_hostname']}", label=f"http://{pf['dns_record_hostname']}")
else:
st.page_link(f"http://{pf['ip_address']}:{pf['external_port']}", label=f"http://{pf['ip_address']}:{pf['external_port']}")
with cols[0]: st.markdown(f"**{pf['protocol'].upper()}**")
with cols[1]: st.text(f"{pf['external_port']} → {pf['internal_port']}")
with cols[2]: st.text(dns_status)
link = pf.get('dns_record_hostname') or f"{pf['ip_address']}:{pf['external_port']}"
st.page_link(f"http://{link}", label=f"http://{link}")
st.markdown("---")
else:
st.text("No port forwardings")
# Container List
for container in pod['containers']:
with st.container():
cols = st.columns([3, 2, 1])
@@ -247,7 +176,6 @@ def render_list():
)
st.markdown("---")
# Delete pod button
if st.button(f"🗑️ Delete Pod {pod['pod_name']}", key=f"delete_pod_{pod['pod_id']}"):
result = st.session_state.client.delete_container_pod(pod['pod_id'])
if result:
+10
View File
@@ -15,6 +15,16 @@ def render_list():
col1, col2, col3 = st.columns([3, 1, 1])
with col1:
st.markdown(f"### {host['name']}")
# Status indicator
status = host.get('status', 'unknown').lower()
if status == 'online':
st.markdown("**🟢 Online**")
elif status == 'offline':
st.markdown("**🔴 Offline**")
else:
st.markdown("**⚪ Unknown**")
st.text(f"Hostname: {host['hostname']}")
st.text(f"Region ID: {host['region_id']}")
# TODO - this bit doesnt work, we arent pulling the labels when we pull the lists of hosts