66 < link rel ="icon " type ="image/x-icon " href ="./images/favicon.ico ">
77 < meta name ="viewport " content ="width=device-width, initial-scale=1 ">
88
9- < script src ="
https://cdn.jsdelivr.net/npm/[email protected] /dist/js/bootstrap.min.js "
> </ script > 9+ < script src ="
https://cdn.jsdelivr.net/npm/[email protected] /dist/js/bootstrap.bundle. min.js "
> </ script > 1010 < link href ="
https://cdn.jsdelivr.net/npm/[email protected] /dist/css/bootstrap.min.css "
rel ="
stylesheet "
> 1111 < script src ="
https://cdn.jsdelivr.net/npm/[email protected] /lib/codemirror.min.js "
> </ script > 1212 < link href ="
https://cdn.jsdelivr.net/npm/[email protected] /lib/codemirror.min.css "
rel ="
stylesheet "
> 13- < script src ="
https://cdn.jsdelivr.net/npm/@popperjs/[email protected] /dist/umd/popper.min.js "
> </ script > 1413 < script src ="
https://cdn.jsdelivr.net/npm/[email protected] /dist/jquery.min.js "
> </ script > 1514 < script src ="
https://cdn.jsdelivr.net/npm/[email protected] /dist/echarts.min.js "
> </ script > 1615
@@ -379,6 +378,162 @@ <h5 class="modal-title pixel-font" id="specialkeysModalLabel">Controls and Optio
379378 </ div >
380379 </ div >
381380
381+ <!-- Modal: Kubernetes Namespaces Help -->
382+ < div class ="modal fade " id ="k8sNamespacesHelpModal " tabindex ="-1 " aria-labelledby ="k8sNamespacesHelpModalLabel " aria-hidden ="true ">
383+ < div class ="modal-dialog modal-lg modal-dialog-scrollable ">
384+ < div class ="modal-content ">
385+ < div class ="modal-header ">
386+ < h5 class ="modal-title " id ="k8sNamespacesHelpModalLabel "> Kubernetes Namespaces</ h5 >
387+ < button type ="button " class ="btn-close " data-bs-dismiss ="modal " aria-label ="Close "> </ button >
388+ </ div >
389+ < div class ="modal-body ">
390+ < p style ="font-size: small; font-weight: normal; "> Provide a < strong > comma-separated</ strong > list of namespaces that KubeInvaders should target. Pods and resources across all listed namespaces will be included in the chaos session.</ p >
391+ < p style ="font-size: small; font-weight: normal; "> < strong > Example:</ strong > </ p >
392+ < div style ="position: relative; ">
393+ < button class ="btn btn-sm btn-outline-secondary " style ="position: absolute; top: 6px; right: 6px; font-size: 11px; " onclick ="copyToClipboard('k8sNamespacesExample') "> Copy</ button >
394+ < pre id ="k8sNamespacesExample " style ="background: #1e1e1e; color: #d4d4d4; padding: 14px; border-radius: 6px; font-size: 11px; "> default,kube-system,my-app</ pre >
395+ </ div >
396+ < p style ="font-size: small; font-weight: normal; margin-top: 12px; "> To list available namespaces in your cluster, run:</ p >
397+ < div style ="position: relative; ">
398+ < button class ="btn btn-sm btn-outline-secondary " style ="position: absolute; top: 6px; right: 6px; font-size: 11px; " onclick ="copyToClipboard('k8sGetNamespacesCmd') "> Copy</ button >
399+ < pre id ="k8sGetNamespacesCmd " style ="background: #1e1e1e; color: #d4d4d4; padding: 14px; border-radius: 6px; font-size: 11px; "> kubectl get namespaces</ pre >
400+ </ div >
401+ </ div >
402+ < div class ="modal-footer ">
403+ < button type ="button " class ="btn btn-secondary " data-bs-dismiss ="modal "> Close</ button >
404+ </ div >
405+ </ div >
406+ </ div >
407+ </ div >
408+
409+ <!-- Modal: Kubernetes Token Help -->
410+ < div class ="modal fade " id ="k8sTokenHelpModal " tabindex ="-1 " aria-labelledby ="k8sTokenHelpModalLabel " aria-hidden ="true ">
411+ < div class ="modal-dialog modal-lg modal-dialog-scrollable ">
412+ < div class ="modal-content ">
413+ < div class ="modal-header ">
414+ < h5 class ="modal-title " id ="k8sTokenHelpModalLabel "> How to create a Kubernetes Service Account Token</ h5 >
415+ < button type ="button " class ="btn-close " data-bs-dismiss ="modal " aria-label ="Close "> </ button >
416+ </ div >
417+ < div class ="modal-body ">
418+ < p style ="font-size: small; font-weight: normal; "> Run the following command to create the required service account, RBAC roles, and a long-lived token secret:</ p >
419+ < div style ="position: relative; ">
420+ < button class ="btn btn-sm btn-outline-secondary " style ="position: absolute; top: 6px; right: 6px; font-size: 11px; " onclick ="copyK8sTokenScript() "> Copy</ button >
421+ < pre id ="k8sTokenScript " style ="background: #1e1e1e; color: #d4d4d4; padding: 14px; border-radius: 6px; font-size: 11px; overflow-x: auto; white-space: pre; "> cat << 'EOF' | kubectl apply -f -
422+ apiVersion: v1
423+ kind: Namespace
424+ metadata:
425+ name: kubeinvaders
426+ ---
427+ apiVersion: rbac.authorization.k8s.io/v1
428+ kind: ClusterRole
429+ metadata:
430+ name: kinv-cr
431+ rules:
432+ - apiGroups:
433+ - ""
434+ resources:
435+ - pods
436+ - pods/log
437+ verbs:
438+ - delete
439+ - apiGroups:
440+ - batch
441+ - extensions
442+ resources:
443+ - jobs
444+ verbs:
445+ - get
446+ - list
447+ - watch
448+ - create
449+ - update
450+ - patch
451+ - delete
452+ - apiGroups:
453+ - "*"
454+ resources:
455+ - "*"
456+ verbs:
457+ - get
458+ - watch
459+ - list
460+ ---
461+ apiVersion: v1
462+ kind: ServiceAccount
463+ metadata:
464+ name: kinv-sa
465+ namespace: kubeinvaders
466+ ---
467+ apiVersion: rbac.authorization.k8s.io/v1
468+ kind: ClusterRoleBinding
469+ metadata:
470+ name: kinv-crb
471+ roleRef:
472+ apiGroup: rbac.authorization.k8s.io
473+ kind: ClusterRole
474+ name: kinv-cr
475+ subjects:
476+ - kind: ServiceAccount
477+ name: kinv-sa
478+ namespace: kubeinvaders
479+ ---
480+ apiVersion: v1
481+ kind: Secret
482+ type: kubernetes.io/service-account-token
483+ metadata:
484+ name: kinv-sa-token
485+ namespace: kubeinvaders
486+ annotations:
487+ kubernetes.io/service-account.name: kinv-sa
488+ ---
489+ apiVersion: rbac.authorization.k8s.io/v1
490+ kind: ClusterRole
491+ metadata:
492+ namespace: default
493+ name: kubevirt-vm-restart-role
494+ rules:
495+ - apiGroups: ["subresources.kubevirt.io"]
496+ resources: ["virtualmachines/restart"]
497+ verbs: ["update"]
498+ ---
499+ apiVersion: rbac.authorization.k8s.io/v1
500+ kind: ClusterRoleBinding
501+ metadata:
502+ name: kubevirt-vm-restart-binding
503+ namespace: default
504+ subjects:
505+ - kind: ServiceAccount
506+ name: kubeinvaders
507+ namespace: kubeinvaders
508+ roleRef:
509+ kind: ClusterRole
510+ name: kubevirt-vm-restart-role
511+ apiGroup: rbac.authorization.k8s.io
512+ EOF</ pre >
513+ </ div >
514+ < p style ="font-size: small; font-weight: normal; margin-top: 12px; "> After applying, retrieve the token with:</ p >
515+ < div style ="position: relative; ">
516+ < button class ="btn btn-sm btn-outline-secondary " style ="position: absolute; top: 6px; right: 6px; font-size: 11px; " onclick ="copyToClipboard('k8sGetTokenCmd') "> Copy</ button >
517+ < pre id ="k8sGetTokenCmd " style ="background: #1e1e1e; color: #d4d4d4; padding: 14px; border-radius: 6px; font-size: 11px; "> kubectl get secret kinv-sa-token -n kubeinvaders -o jsonpath='{.data.token}' | base64 --decode</ pre >
518+ </ div >
519+ </ div >
520+ < div class ="modal-footer ">
521+ < button type ="button " class ="btn btn-secondary " data-bs-dismiss ="modal "> Close</ button >
522+ </ div >
523+ </ div >
524+ </ div >
525+ </ div >
526+ < script >
527+ function copyToClipboard ( elementId ) {
528+ const text = document . getElementById ( elementId ) . innerText ;
529+ navigator . clipboard . writeText ( text ) ;
530+ }
531+ function copyK8sTokenScript ( ) {
532+ const raw = document . getElementById ( 'k8sTokenScript' ) . innerText ;
533+ navigator . clipboard . writeText ( raw ) ;
534+ }
535+ </ script >
536+
382537 < div class ="container " id ="gameContainer ">
383538 <!-- START FIRST ROW -->
384539 < div class ="row custom-btn-group " style ="margin-top: 2%; ">
@@ -392,10 +547,10 @@ <h2>Kubernetes Connection</h2>
392547 < label for ="k8s_api_endpoint "> Kubernetes API Endpoint</ label >
393548 < input type ="text " id ="k8s_api_endpoint " name ="k8s_api_endpoint " placeholder ="https://kubernetes.default.svc ">
394549
395- < label for ="k8s_token "> Kubernetes Token</ label >
550+ < label for ="k8s_token "> Kubernetes Token < button type =" button " class =" btn btn-sm btn-outline-secondary " data-bs-toggle =" modal " data-bs-target =" #k8sTokenHelpModal " title =" How to create a service account token " style =" padding: 1px 6px; font-size: 11px; line-height: 1.4; " > ⓘ </ button > </ label >
396551 < input type ="password " id ="k8s_token " name ="k8s_token " placeholder ="Enter your token ">
397552
398- < label for ="k8s_namespaces "> Kubernetes Namespaces</ label >
553+ < label for ="k8s_namespaces "> Kubernetes Namespaces < button type =" button " class =" btn btn-sm btn-outline-secondary " data-bs-toggle =" modal " data-bs-target =" #k8sNamespacesHelpModal " title =" About Kubernetes Namespaces " style =" padding: 1px 6px; font-size: 11px; line-height: 1.4; " > ⓘ </ button > </ label >
399554 < input
400555 type ="text "
401556 id ="k8s_namespaces "
0 commit comments