Compare commits

..

No commits in common. "7ba927e1a70db99d9c9ed59ef7551bae04721390" and "e046605ae64f3ec772831e236b0f2dfbbe670448" have entirely different histories.

4 changed files with 8 additions and 81 deletions

View File

@ -117,16 +117,6 @@ fn extract_context(content: &str) -> Result<String, String> {
let value: serde_yaml::Value =
serde_yaml::from_str(content).map_err(|e| format!("Invalid kubeconfig YAML: {}", e))?;
// Prefer current-context — this is what kubectl uses by default and what the
// user intends when they upload their kubeconfig. Falling back to contexts[0]
// picks the wrong entry when the file has multiple contexts.
if let Some(current) = value.get("current-context").and_then(|c| c.as_str()) {
if !current.is_empty() {
return Ok(current.to_string());
}
}
// No current-context set — fall back to the first context in the list
let contexts = value
.get("contexts")
.and_then(|c| c.as_sequence())
@ -136,9 +126,8 @@ fn extract_context(content: &str) -> Result<String, String> {
return Err("No contexts found in kubeconfig".to_string());
}
contexts[0]
.get("name")
.and_then(|n| n.as_str())
let first_context = contexts[0].get("name").and_then(|n| n.as_str());
first_context
.map(|s| s.to_string())
.ok_or_else(|| "Context name not found".to_string())
}

View File

@ -41,24 +41,11 @@ pub async fn upload_kubeconfig(
// Generate ID
let id = uuid::Uuid::now_v7().to_string();
// Parse kubeconfig to extract context.
// Use current-context to select the right entry — the user's kubeconfig may
// have multiple contexts and current-context is the one kubectl defaults to.
// Parse kubeconfig to extract context
let contexts = crate::shell::kubeconfig::parse_kubeconfig_contexts(&content)?;
let current_context_name = crate::shell::kubeconfig::extract_current_context_name(&content);
let context = if let Some(ref current) = current_context_name {
contexts
.iter()
.find(|c| &c.name == current)
.or_else(|| contexts.first())
.ok_or_else(|| "No contexts found in kubeconfig".to_string())?
} else {
contexts
.first()
.ok_or_else(|| "No contexts found in kubeconfig".to_string())?
};
let context = contexts
.first()
.ok_or_else(|| "No contexts found in kubeconfig".to_string())?;
// Encrypt content
let encrypted_content = crate::integrations::auth::encrypt_token(&content)?;

View File

@ -30,26 +30,6 @@ pub async fn auto_detect_kubeconfig(_state: &AppState) -> Result<(), String> {
Err("Kubeconfig auto-detection not yet implemented".to_string())
}
/// Return the `current-context` value from a kubeconfig YAML, if set.
/// Uses simple line scanning so it stays consistent with `parse_kubeconfig_contexts`.
pub fn extract_current_context_name(content: &str) -> Option<String> {
for line in content.lines() {
let trimmed = line.trim();
if trimmed.starts_with("current-context:") {
let val = trimmed
.trim_start_matches("current-context:")
.trim()
.trim_matches('"')
.trim_matches('\'')
.to_string();
if !val.is_empty() {
return Some(val);
}
}
}
None
}
pub fn parse_kubeconfig_contexts(content: &str) -> Result<Vec<KubeconfigContext>, String> {
// Parse YAML kubeconfig file
// Simple string parsing to extract contexts and cluster URLs

View File

@ -188,29 +188,10 @@ interface SelectContextValue {
onChange: (value: string) => void;
open: boolean;
setOpen: (open: boolean) => void;
labelMap: Map<string, React.ReactNode>;
}
const SelectContext = React.createContext<SelectContextValue | null>(null);
/** Walk a React node tree collecting SelectItem value→children mappings. */
function collectLabels(
nodes: React.ReactNode,
map: Map<string, React.ReactNode>
): void {
React.Children.forEach(nodes, (child) => {
if (!React.isValidElement(child)) return;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const props = child.props as any;
if (child.type === SelectItem && typeof props.value === "string") {
map.set(props.value, props.children);
}
if (props.children) {
collectLabels(props.children as React.ReactNode, map);
}
});
}
interface SelectProps {
value?: string;
onValueChange?: (value: string) => void;
@ -226,13 +207,8 @@ export function Select({ value = "", onValueChange, children }: SelectProps) {
},
[onValueChange]
);
const labelMap = React.useMemo(() => {
const map = new Map<string, React.ReactNode>();
collectLabels(children, map);
return map;
}, [children]);
return (
<SelectContext.Provider value={{ value, onChange, open, setOpen, labelMap }}>
<SelectContext.Provider value={{ value, onChange, open, setOpen }}>
<div className="relative">{children}</div>
</SelectContext.Provider>
);
@ -266,12 +242,7 @@ export function SelectTrigger({
export function SelectValue({ placeholder }: { placeholder?: string }) {
const ctx = React.useContext(SelectContext)!;
const label = ctx.value ? ctx.labelMap.get(ctx.value) : undefined;
return (
<span className={ctx.value ? "text-foreground" : "text-muted-foreground"}>
{label ?? (ctx.value ? ctx.value : placeholder)}
</span>
);
return <span className={ctx.value ? "text-foreground" : "text-muted-foreground"}>{ctx.value || placeholder}</span>;
}
export function SelectContent({