added app icon, introduce kubernetesservice interface and logging

This commit is contained in:
2023-08-01 20:39:25 +02:00
parent ee6544c641
commit 12ef9680d0
9 changed files with 189 additions and 154 deletions

View 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))

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

View File

@@ -8,6 +8,7 @@
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<Configurations>Debug;Release</Configurations>
<Platforms>AnyCPU</Platforms>
<ApplicationIcon>Assets/app.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DefineConstants>TRACE</DefineConstants>
@@ -28,7 +29,9 @@
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.1" />
<PackageReference Include="KubernetesClient" Version="11.0.44" />
<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.File" Version="5.0.0" />
<PackageReference Include="SharpZipLib" Version="1.4.2" />
</ItemGroup>
</Project>

View File

@@ -16,8 +16,8 @@ class Program
{
Log.Logger = new LoggerConfiguration()
//.Filter.ByIncludingOnly(Matching.WithProperty("Area", LogArea.Control))
.MinimumLevel.Verbose()
.WriteTo.Console()
.MinimumLevel.Information()
.WriteTo.Async(a => a.File("app.log"))
.CreateLogger();
BuildAvaloniaApp()

View 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);
}

View File

@@ -14,7 +14,7 @@ using static ICSharpCode.SharpZipLib.Core.StreamUtils;
namespace K8sFileBrowser.Services;
public class KubernetesService
public class KubernetesService : IKubernetesService
{
private readonly K8SConfiguration _k8SConfiguration;
private IKubernetes _kubernetesClient = null!;
@@ -98,9 +98,8 @@ public class KubernetesService
_kubernetesClient = kubernetesClient;
}
public async Task DownloadFile(Namespace? selectedNamespace, Pod? selectedPod, FileInformation selectedFile,
string? saveFileName)
string? saveFileName, CancellationToken cancellationToken = default)
{
Log.Information("{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 tarInputStream = new TarInputStream(stdOut, Encoding.Default);
var entry = await tarInputStream.GetNextEntryAsync(default);
var entry = await tarInputStream.GetNextEntryAsync(cancellationToken);
if (entry == null)
{
throw new IOException("Copy command failed: no files found");
@@ -119,7 +118,7 @@ public class KubernetesService
var bytes = new byte[entry.Size];
ReadFully( tarInputStream, bytes );
await outputFileStream.WriteAsync(bytes, default);
await outputFileStream.WriteAsync(bytes, cancellationToken);
}
catch (Exception ex)
{
@@ -129,7 +128,7 @@ public class KubernetesService
using var streamReader = new StreamReader(stdError);
while (streamReader.EndOfStream == false)
{
var error = await streamReader.ReadToEndAsync(default);
var error = await streamReader.ReadToEndAsync(cancellationToken);
Log.Error(error);
}
});

View File

@@ -15,6 +15,7 @@ public class MainWindowViewModel : ViewModelBase
public IEnumerable<ClusterContext> ClusterContexts => _clusterContexts.Value;
private ClusterContext? _selectedClusterContext;
public ClusterContext? SelectedClusterContext
{
get => _selectedClusterContext;
@@ -25,6 +26,7 @@ public class MainWindowViewModel : ViewModelBase
public IEnumerable<Namespace> Namespaces => _namespaces.Value;
private Namespace? _selectedNamespace;
public Namespace? SelectedNamespace
{
get => _selectedNamespace;
@@ -35,6 +37,7 @@ public class MainWindowViewModel : ViewModelBase
public IEnumerable<Pod> Pods => _pods.Value;
private Pod? _selectedPod;
public Pod? SelectedPod
{
get => _selectedPod;
@@ -45,6 +48,7 @@ public class MainWindowViewModel : ViewModelBase
public IEnumerable<FileInformation> FileInformation => _fileInformation.Value;
private FileInformation? _selectedFile;
public FileInformation? SelectedFile
{
get => _selectedFile;
@@ -52,6 +56,7 @@ public class MainWindowViewModel : ViewModelBase
}
private string? _selectedPath;
public string? SelectedPath
{
get => _selectedPath;
@@ -59,6 +64,7 @@ public class MainWindowViewModel : ViewModelBase
}
private bool _isDownloadActive;
public bool IsDownloadActive
{
get => _isDownloadActive;
@@ -72,7 +78,8 @@ public class MainWindowViewModel : ViewModelBase
public MainWindowViewModel()
{
var kubernetesService = new KubernetesService();
//TODO: use dependency injection to get the kubernetes service
IKubernetesService kubernetesService = new KubernetesService();
var isFile = this
.WhenAnyValue(x => x.SelectedFile, x => x.IsDownloadActive)
@@ -86,15 +93,15 @@ public class MainWindowViewModel : ViewModelBase
.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);
OpenCommand = ReactiveCommand.Create(() => { SelectedPath = SelectedFile != null ? SelectedFile!.Name : "/"; },
isDirectory, RxApp.MainThreadScheduler);
DownloadCommand = ReactiveCommand.CreateFromTask(async () =>
{
await Observable.StartAsync(async () => {
var fileName = SelectedFile!.Name.Substring(SelectedFile!.Name.LastIndexOf('/') + 1, SelectedFile!.Name.Length - SelectedFile!.Name.LastIndexOf('/') - 1);
await Observable.StartAsync(async () =>
{
var fileName = SelectedFile!.Name.Substring(SelectedFile!.Name.LastIndexOf('/') + 1,
SelectedFile!.Name.Length - SelectedFile!.Name.LastIndexOf('/') - 1);
var saveFileName = await ApplicationHelper.SaveFile(".", fileName);
if (saveFileName != null)
{

View File

@@ -7,7 +7,7 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="K8sFileBrowser.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
Icon="/Assets/avalonia-logo.ico"
Icon="/Assets/app.ico"
Title="K8sFileBrowser">
<Design.DataContext>