mirror of
https://github.com/frosch95/K8sFileBrowser.git
synced 2026-04-11 12:58:22 +02:00
added app icon, introduce kubernetesservice interface and logging
This commit is contained in:
6
K8sFileBrowser/Assets/about.txt
Normal file
6
K8sFileBrowser/Assets/about.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
This favicon was generated using the following font:
|
||||||
|
|
||||||
|
- Font Title: Genos
|
||||||
|
- Font Author: Copyright 2011 The Genos Project Authors (https://github.com/googlefonts/genos)
|
||||||
|
- Font Source: http://fonts.gstatic.com/s/genos/v10/SlGNmQqPqpUOYTYjacb0Hc91fTwVA0_orUK6K7ZsAg.ttf
|
||||||
|
- Font License: SIL Open Font License, 1.1 (http://scripts.sil.org/OFL))
|
||||||
BIN
K8sFileBrowser/Assets/app.ico
Normal file
BIN
K8sFileBrowser/Assets/app.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 172 KiB |
@@ -8,6 +8,7 @@
|
|||||||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
||||||
<Configurations>Debug;Release</Configurations>
|
<Configurations>Debug;Release</Configurations>
|
||||||
<Platforms>AnyCPU</Platforms>
|
<Platforms>AnyCPU</Platforms>
|
||||||
|
<ApplicationIcon>Assets/app.ico</ApplicationIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
@@ -28,7 +29,9 @@
|
|||||||
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.1" />
|
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.1" />
|
||||||
<PackageReference Include="KubernetesClient" Version="11.0.44" />
|
<PackageReference Include="KubernetesClient" Version="11.0.44" />
|
||||||
<PackageReference Include="Serilog" Version="3.0.1" />
|
<PackageReference Include="Serilog" Version="3.0.1" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||||
<PackageReference Include="SharpZipLib" Version="1.4.2" />
|
<PackageReference Include="SharpZipLib" Version="1.4.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ class Program
|
|||||||
{
|
{
|
||||||
Log.Logger = new LoggerConfiguration()
|
Log.Logger = new LoggerConfiguration()
|
||||||
//.Filter.ByIncludingOnly(Matching.WithProperty("Area", LogArea.Control))
|
//.Filter.ByIncludingOnly(Matching.WithProperty("Area", LogArea.Control))
|
||||||
.MinimumLevel.Verbose()
|
.MinimumLevel.Information()
|
||||||
.WriteTo.Console()
|
.WriteTo.Async(a => a.File("app.log"))
|
||||||
.CreateLogger();
|
.CreateLogger();
|
||||||
|
|
||||||
BuildAvaloniaApp()
|
BuildAvaloniaApp()
|
||||||
|
|||||||
20
K8sFileBrowser/Services/IKubernetesService.cs
Normal file
20
K8sFileBrowser/Services/IKubernetesService.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// // Copyright (c) Vector Informatik GmbH. All rights reserved.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using K8sFileBrowser.Models;
|
||||||
|
|
||||||
|
namespace K8sFileBrowser.Services;
|
||||||
|
|
||||||
|
public interface IKubernetesService
|
||||||
|
{
|
||||||
|
IEnumerable<ClusterContext> GetClusterContexts();
|
||||||
|
string GetCurrentContext();
|
||||||
|
void SwitchClusterContext(ClusterContext clusterContext);
|
||||||
|
IEnumerable<Namespace> GetNamespaces();
|
||||||
|
IEnumerable<Pod> GetPods(string namespaceName);
|
||||||
|
IList<FileInformation> GetFiles(string namespaceName, string podName, string containerName, string path);
|
||||||
|
Task DownloadFile(Namespace? selectedNamespace, Pod? selectedPod, FileInformation selectedFile,
|
||||||
|
string? saveFileName, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ using static ICSharpCode.SharpZipLib.Core.StreamUtils;
|
|||||||
|
|
||||||
namespace K8sFileBrowser.Services;
|
namespace K8sFileBrowser.Services;
|
||||||
|
|
||||||
public class KubernetesService
|
public class KubernetesService : IKubernetesService
|
||||||
{
|
{
|
||||||
private readonly K8SConfiguration _k8SConfiguration;
|
private readonly K8SConfiguration _k8SConfiguration;
|
||||||
private IKubernetes _kubernetesClient = null!;
|
private IKubernetes _kubernetesClient = null!;
|
||||||
@@ -98,9 +98,8 @@ public class KubernetesService
|
|||||||
_kubernetesClient = kubernetesClient;
|
_kubernetesClient = kubernetesClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task DownloadFile(Namespace? selectedNamespace, Pod? selectedPod, FileInformation selectedFile,
|
public async Task DownloadFile(Namespace? selectedNamespace, Pod? selectedPod, FileInformation selectedFile,
|
||||||
string? saveFileName)
|
string? saveFileName, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
Log.Information("{SelectedNamespace} - {SelectedPod} - {SelectedFile} - {SaveFileName}",
|
Log.Information("{SelectedNamespace} - {SelectedPod} - {SelectedFile} - {SaveFileName}",
|
||||||
selectedNamespace, selectedPod, selectedFile, saveFileName);
|
selectedNamespace, selectedPod, selectedFile, saveFileName);
|
||||||
@@ -111,7 +110,7 @@ public class KubernetesService
|
|||||||
await using var outputFileStream = File.OpenWrite(saveFileName!);
|
await using var outputFileStream = File.OpenWrite(saveFileName!);
|
||||||
await using var tarInputStream = new TarInputStream(stdOut, Encoding.Default);
|
await using var tarInputStream = new TarInputStream(stdOut, Encoding.Default);
|
||||||
|
|
||||||
var entry = await tarInputStream.GetNextEntryAsync(default);
|
var entry = await tarInputStream.GetNextEntryAsync(cancellationToken);
|
||||||
if (entry == null)
|
if (entry == null)
|
||||||
{
|
{
|
||||||
throw new IOException("Copy command failed: no files found");
|
throw new IOException("Copy command failed: no files found");
|
||||||
@@ -119,7 +118,7 @@ public class KubernetesService
|
|||||||
|
|
||||||
var bytes = new byte[entry.Size];
|
var bytes = new byte[entry.Size];
|
||||||
ReadFully( tarInputStream, bytes );
|
ReadFully( tarInputStream, bytes );
|
||||||
await outputFileStream.WriteAsync(bytes, default);
|
await outputFileStream.WriteAsync(bytes, cancellationToken);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -129,7 +128,7 @@ public class KubernetesService
|
|||||||
using var streamReader = new StreamReader(stdError);
|
using var streamReader = new StreamReader(stdError);
|
||||||
while (streamReader.EndOfStream == false)
|
while (streamReader.EndOfStream == false)
|
||||||
{
|
{
|
||||||
var error = await streamReader.ReadToEndAsync(default);
|
var error = await streamReader.ReadToEndAsync(cancellationToken);
|
||||||
Log.Error(error);
|
Log.Error(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,154 +11,161 @@ namespace K8sFileBrowser.ViewModels;
|
|||||||
|
|
||||||
public class MainWindowViewModel : ViewModelBase
|
public class MainWindowViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
private readonly ObservableAsPropertyHelper<IEnumerable<ClusterContext>> _clusterContexts;
|
private readonly ObservableAsPropertyHelper<IEnumerable<ClusterContext>> _clusterContexts;
|
||||||
public IEnumerable<ClusterContext> ClusterContexts => _clusterContexts.Value;
|
public IEnumerable<ClusterContext> ClusterContexts => _clusterContexts.Value;
|
||||||
|
|
||||||
private ClusterContext? _selectedClusterContext;
|
private ClusterContext? _selectedClusterContext;
|
||||||
public ClusterContext? SelectedClusterContext
|
|
||||||
|
public ClusterContext? SelectedClusterContext
|
||||||
|
{
|
||||||
|
get => _selectedClusterContext;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _selectedClusterContext, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly ObservableAsPropertyHelper<IEnumerable<Namespace>> _namespaces;
|
||||||
|
public IEnumerable<Namespace> Namespaces => _namespaces.Value;
|
||||||
|
|
||||||
|
private Namespace? _selectedNamespace;
|
||||||
|
|
||||||
|
public Namespace? SelectedNamespace
|
||||||
|
{
|
||||||
|
get => _selectedNamespace;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _selectedNamespace, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly ObservableAsPropertyHelper<IEnumerable<Pod>> _pods;
|
||||||
|
public IEnumerable<Pod> Pods => _pods.Value;
|
||||||
|
|
||||||
|
private Pod? _selectedPod;
|
||||||
|
|
||||||
|
public Pod? SelectedPod
|
||||||
|
{
|
||||||
|
get => _selectedPod;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _selectedPod, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly ObservableAsPropertyHelper<IEnumerable<FileInformation>> _fileInformation;
|
||||||
|
public IEnumerable<FileInformation> FileInformation => _fileInformation.Value;
|
||||||
|
|
||||||
|
private FileInformation? _selectedFile;
|
||||||
|
|
||||||
|
public FileInformation? SelectedFile
|
||||||
|
{
|
||||||
|
get => _selectedFile;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _selectedFile, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string? _selectedPath;
|
||||||
|
|
||||||
|
public string? SelectedPath
|
||||||
|
{
|
||||||
|
get => _selectedPath;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _selectedPath, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _isDownloadActive;
|
||||||
|
|
||||||
|
public bool IsDownloadActive
|
||||||
|
{
|
||||||
|
get => _isDownloadActive;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _isDownloadActive, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReactiveCommand<Unit, Unit> DownloadCommand { get; }
|
||||||
|
public ReactiveCommand<Unit, Unit> ParentCommand { get; }
|
||||||
|
public ReactiveCommand<Unit, Unit> OpenCommand { get; }
|
||||||
|
|
||||||
|
|
||||||
|
public MainWindowViewModel()
|
||||||
|
{
|
||||||
|
//TODO: use dependency injection to get the kubernetes service
|
||||||
|
IKubernetesService kubernetesService = new KubernetesService();
|
||||||
|
|
||||||
|
var isFile = this
|
||||||
|
.WhenAnyValue(x => x.SelectedFile, x => x.IsDownloadActive)
|
||||||
|
.Select(x => x is { Item1.Type: FileType.File, Item2: false });
|
||||||
|
|
||||||
|
var isDirectory = this
|
||||||
|
.WhenAnyValue(x => x.SelectedFile, x => x.IsDownloadActive)
|
||||||
|
.Select(x => x is { Item1.Type: FileType.Directory, Item2: false });
|
||||||
|
|
||||||
|
var isNotRoot = this
|
||||||
|
.WhenAnyValue(x => x.SelectedPath, x => x.IsDownloadActive)
|
||||||
|
.Select(x => x.Item1 is not "/" && !x.Item2);
|
||||||
|
|
||||||
|
OpenCommand = ReactiveCommand.Create(() => { SelectedPath = SelectedFile != null ? SelectedFile!.Name : "/"; },
|
||||||
|
isDirectory, RxApp.MainThreadScheduler);
|
||||||
|
|
||||||
|
DownloadCommand = ReactiveCommand.CreateFromTask(async () =>
|
||||||
{
|
{
|
||||||
get => _selectedClusterContext;
|
await Observable.StartAsync(async () =>
|
||||||
set => this.RaiseAndSetIfChanged(ref _selectedClusterContext, value);
|
{
|
||||||
}
|
var fileName = SelectedFile!.Name.Substring(SelectedFile!.Name.LastIndexOf('/') + 1,
|
||||||
|
SelectedFile!.Name.Length - SelectedFile!.Name.LastIndexOf('/') - 1);
|
||||||
private readonly ObservableAsPropertyHelper<IEnumerable<Namespace>> _namespaces;
|
var saveFileName = await ApplicationHelper.SaveFile(".", fileName);
|
||||||
public IEnumerable<Namespace> Namespaces => _namespaces.Value;
|
if (saveFileName != null)
|
||||||
|
|
||||||
private Namespace? _selectedNamespace;
|
|
||||||
public Namespace? SelectedNamespace
|
|
||||||
{
|
|
||||||
get => _selectedNamespace;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _selectedNamespace, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly ObservableAsPropertyHelper<IEnumerable<Pod>> _pods;
|
|
||||||
public IEnumerable<Pod> Pods => _pods.Value;
|
|
||||||
|
|
||||||
private Pod? _selectedPod;
|
|
||||||
public Pod? SelectedPod
|
|
||||||
{
|
|
||||||
get => _selectedPod;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _selectedPod, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly ObservableAsPropertyHelper<IEnumerable<FileInformation>> _fileInformation;
|
|
||||||
public IEnumerable<FileInformation> FileInformation => _fileInformation.Value;
|
|
||||||
|
|
||||||
private FileInformation? _selectedFile;
|
|
||||||
public FileInformation? SelectedFile
|
|
||||||
{
|
|
||||||
get => _selectedFile;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _selectedFile, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string? _selectedPath;
|
|
||||||
public string? SelectedPath
|
|
||||||
{
|
|
||||||
get => _selectedPath;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _selectedPath, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _isDownloadActive;
|
|
||||||
public bool IsDownloadActive
|
|
||||||
{
|
|
||||||
get => _isDownloadActive;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _isDownloadActive, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReactiveCommand<Unit, Unit> DownloadCommand { get; }
|
|
||||||
public ReactiveCommand<Unit, Unit> ParentCommand { get; }
|
|
||||||
public ReactiveCommand<Unit, Unit> OpenCommand { get; }
|
|
||||||
|
|
||||||
|
|
||||||
public MainWindowViewModel()
|
|
||||||
{
|
|
||||||
var kubernetesService = new KubernetesService();
|
|
||||||
|
|
||||||
var isFile = this
|
|
||||||
.WhenAnyValue(x => x.SelectedFile, x => x.IsDownloadActive)
|
|
||||||
.Select(x => x is { Item1.Type: FileType.File, Item2: false });
|
|
||||||
|
|
||||||
var isDirectory = this
|
|
||||||
.WhenAnyValue(x => x.SelectedFile, x => x.IsDownloadActive)
|
|
||||||
.Select(x => x is { Item1.Type: FileType.Directory, Item2: false });
|
|
||||||
|
|
||||||
var isNotRoot = this
|
|
||||||
.WhenAnyValue(x => x.SelectedPath, x => x.IsDownloadActive)
|
|
||||||
.Select(x => x.Item1 is not "/" && !x.Item2);
|
|
||||||
|
|
||||||
OpenCommand = ReactiveCommand.Create(() =>
|
|
||||||
{
|
{
|
||||||
SelectedPath = SelectedFile != null ? SelectedFile!.Name : "/";
|
IsDownloadActive = true;
|
||||||
}, isDirectory, RxApp.MainThreadScheduler);
|
await kubernetesService.DownloadFile(SelectedNamespace, SelectedPod, SelectedFile, saveFileName);
|
||||||
|
IsDownloadActive = false;
|
||||||
|
}
|
||||||
|
}, RxApp.TaskpoolScheduler);
|
||||||
|
}, isFile, RxApp.MainThreadScheduler);
|
||||||
|
|
||||||
DownloadCommand = ReactiveCommand.CreateFromTask(async () =>
|
ParentCommand = ReactiveCommand.Create(() =>
|
||||||
{
|
{
|
||||||
await Observable.StartAsync(async () => {
|
SelectedPath = SelectedPath![..SelectedPath!.LastIndexOf('/')];
|
||||||
var fileName = SelectedFile!.Name.Substring(SelectedFile!.Name.LastIndexOf('/') + 1, SelectedFile!.Name.Length - SelectedFile!.Name.LastIndexOf('/') - 1);
|
if (SelectedPath!.Length == 0)
|
||||||
var saveFileName = await ApplicationHelper.SaveFile(".", fileName);
|
{
|
||||||
if (saveFileName != null)
|
SelectedPath = "/";
|
||||||
{
|
}
|
||||||
IsDownloadActive = true;
|
}, isNotRoot, RxApp.MainThreadScheduler);
|
||||||
await kubernetesService.DownloadFile(SelectedNamespace, SelectedPod, SelectedFile, saveFileName);
|
|
||||||
IsDownloadActive = false;
|
|
||||||
}
|
|
||||||
}, RxApp.TaskpoolScheduler);
|
|
||||||
}, isFile, RxApp.MainThreadScheduler);
|
|
||||||
|
|
||||||
ParentCommand = ReactiveCommand.Create(() =>
|
// read the cluster contexts
|
||||||
{
|
_namespaces = this
|
||||||
SelectedPath = SelectedPath![..SelectedPath!.LastIndexOf('/')];
|
.WhenAnyValue(c => c.SelectedClusterContext)
|
||||||
if (SelectedPath!.Length == 0)
|
.Throttle(TimeSpan.FromMilliseconds(10))
|
||||||
{
|
.Where(context => context != null)
|
||||||
SelectedPath = "/";
|
.Select(context =>
|
||||||
}
|
{
|
||||||
}, isNotRoot, RxApp.MainThreadScheduler);
|
kubernetesService.SwitchClusterContext(context!);
|
||||||
|
return kubernetesService.GetNamespaces();
|
||||||
|
})
|
||||||
|
.ObserveOn(RxApp.MainThreadScheduler)
|
||||||
|
.ToProperty(this, x => x.Namespaces);
|
||||||
|
|
||||||
// read the cluster contexts
|
// read the pods when the namespace changes
|
||||||
_namespaces = this
|
_pods = this
|
||||||
.WhenAnyValue(c => c.SelectedClusterContext)
|
.WhenAnyValue(c => c.SelectedNamespace)
|
||||||
.Throttle(TimeSpan.FromMilliseconds(10))
|
.Throttle(TimeSpan.FromMilliseconds(10))
|
||||||
.Where(context => context != null)
|
.Where(ns => ns != null)
|
||||||
.Select(context =>
|
.Select(ns => kubernetesService.GetPods(ns!.Name))
|
||||||
{
|
.ObserveOn(RxApp.MainThreadScheduler)
|
||||||
kubernetesService.SwitchClusterContext(context!);
|
.ToProperty(this, x => x.Pods);
|
||||||
return kubernetesService.GetNamespaces();
|
|
||||||
})
|
|
||||||
.ObserveOn(RxApp.MainThreadScheduler)
|
|
||||||
.ToProperty(this, x => x.Namespaces);
|
|
||||||
|
|
||||||
// read the pods when the namespace changes
|
// read the file information when the path changes
|
||||||
_pods = this
|
_fileInformation = this
|
||||||
.WhenAnyValue(c => c.SelectedNamespace)
|
.WhenAnyValue(c => c.SelectedPath, c => c.SelectedPod, c => c.SelectedNamespace)
|
||||||
.Throttle(TimeSpan.FromMilliseconds(10))
|
.Throttle(TimeSpan.FromMilliseconds(10))
|
||||||
.Where(ns => ns != null)
|
.Select(x => x.Item3 == null || x.Item2 == null
|
||||||
.Select(ns => kubernetesService.GetPods(ns!.Name))
|
? new List<FileInformation>()
|
||||||
.ObserveOn(RxApp.MainThreadScheduler)
|
: kubernetesService.GetFiles(x.Item3!.Name, x.Item2!.Name, x.Item2!.Containers.First(),
|
||||||
.ToProperty(this, x => x.Pods);
|
x.Item1))
|
||||||
|
.ObserveOn(RxApp.MainThreadScheduler)
|
||||||
|
.ToProperty(this, x => x.FileInformation);
|
||||||
|
|
||||||
// read the file information when the path changes
|
// reset the path when the pod or namespace changes
|
||||||
_fileInformation = this
|
this.WhenAnyValue(c => c.SelectedPod, c => c.SelectedNamespace)
|
||||||
.WhenAnyValue(c => c.SelectedPath, c => c.SelectedPod, c => c.SelectedNamespace)
|
.Subscribe(x => SelectedPath = "/");
|
||||||
.Throttle(TimeSpan.FromMilliseconds(10))
|
|
||||||
.Select(x => x.Item3 == null || x.Item2 == null
|
|
||||||
? new List<FileInformation>()
|
|
||||||
: kubernetesService.GetFiles(x.Item3!.Name, x.Item2!.Name, x.Item2!.Containers.First(),
|
|
||||||
x.Item1))
|
|
||||||
.ObserveOn(RxApp.MainThreadScheduler)
|
|
||||||
.ToProperty(this, x => x.FileInformation);
|
|
||||||
|
|
||||||
// reset the path when the pod or namespace changes
|
// load the cluster contexts when the view model is created
|
||||||
this.WhenAnyValue(c => c.SelectedPod, c => c.SelectedNamespace)
|
var loadContexts = ReactiveCommand
|
||||||
.Subscribe(x => SelectedPath = "/");
|
.Create<Unit, IEnumerable<ClusterContext>>(_ => kubernetesService.GetClusterContexts());
|
||||||
|
_clusterContexts = loadContexts.Execute().ToProperty(
|
||||||
|
this, x => x.ClusterContexts, scheduler: RxApp.MainThreadScheduler);
|
||||||
|
|
||||||
// load the cluster contexts when the view model is created
|
// select the current cluster context
|
||||||
var loadContexts = ReactiveCommand
|
SelectedClusterContext = ClusterContexts
|
||||||
.Create<Unit, IEnumerable<ClusterContext>>(_ => kubernetesService.GetClusterContexts());
|
.FirstOrDefault(x => x.Name == kubernetesService.GetCurrentContext());
|
||||||
_clusterContexts = loadContexts.Execute().ToProperty(
|
}
|
||||||
this, x => x.ClusterContexts, scheduler: RxApp.MainThreadScheduler);
|
|
||||||
|
|
||||||
// select the current cluster context
|
|
||||||
SelectedClusterContext = ClusterContexts
|
|
||||||
.FirstOrDefault(x => x.Name == kubernetesService.GetCurrentContext());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="K8sFileBrowser.Views.MainWindow"
|
x:Class="K8sFileBrowser.Views.MainWindow"
|
||||||
x:DataType="vm:MainWindowViewModel"
|
x:DataType="vm:MainWindowViewModel"
|
||||||
Icon="/Assets/avalonia-logo.ico"
|
Icon="/Assets/app.ico"
|
||||||
Title="K8sFileBrowser">
|
Title="K8sFileBrowser">
|
||||||
|
|
||||||
<Design.DataContext>
|
<Design.DataContext>
|
||||||
|
|||||||
Reference in New Issue
Block a user