Copy local file to pod using tar (#962)
* Copy local file to pod using tar * Update examples/cp/Cp.cs Co-authored-by: Boshi Lian <farmer1992@gmail.com> * File names as command line args, default encoding * command line args Co-authored-by: Boshi Lian <farmer1992@gmail.com>
This commit is contained in:
126
examples/cp/Cp.cs
Normal file
126
examples/cp/Cp.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using k8s;
|
||||
using ICSharpCode.SharpZipLib.Tar;
|
||||
using System.Threading;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace cp
|
||||
{
|
||||
internal class Cp
|
||||
{
|
||||
private static IKubernetes client;
|
||||
|
||||
private static async Task Main(string[] args)
|
||||
{
|
||||
var config = KubernetesClientConfiguration.BuildConfigFromConfigFile();
|
||||
client = new Kubernetes(config);
|
||||
|
||||
|
||||
var pods = client.CoreV1.ListNamespacedPod("default", null, null, null, $"job-name=upload-demo");
|
||||
var pod = pods.Items.First();
|
||||
|
||||
await CopyFileToPodAsync(pod.Metadata.Name, "default", "upload-demo", args[0], $"home/{args[1]}");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private static void ValidatePathParameters(string sourcePath, string destinationPath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(sourcePath))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(sourcePath)} cannot be null or whitespace");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(destinationPath))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(destinationPath)} cannot be null or whitespace");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static async Task<int> CopyFileToPodAsync(string name, string @namespace, string container, string sourceFilePath, string destinationFilePath, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
// All other parameters are being validated by MuxedStreamNamespacedPodExecAsync called by NamespacedPodExecAsync
|
||||
ValidatePathParameters(sourceFilePath, destinationFilePath);
|
||||
|
||||
// The callback which processes the standard input, standard output and standard error of exec method
|
||||
var handler = new ExecAsyncCallback(async (stdIn, stdOut, stdError) =>
|
||||
{
|
||||
var fileInfo = new FileInfo(destinationFilePath);
|
||||
try
|
||||
{
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
using (var inputFileStream = File.OpenRead(sourceFilePath))
|
||||
using (var tarOutputStream = new TarOutputStream(memoryStream, Encoding.Default))
|
||||
{
|
||||
tarOutputStream.IsStreamOwner = false;
|
||||
|
||||
var fileSize = inputFileStream.Length;
|
||||
var entry = TarEntry.CreateTarEntry(fileInfo.Name);
|
||||
|
||||
entry.Size = fileSize;
|
||||
|
||||
tarOutputStream.PutNextEntry(entry);
|
||||
await inputFileStream.CopyToAsync(tarOutputStream);
|
||||
tarOutputStream.CloseEntry();
|
||||
}
|
||||
|
||||
memoryStream.Position = 0;
|
||||
|
||||
const int bufferSize = 31 * 1024 * 1024; // must be lower than 32 * 1024 * 1024
|
||||
byte[] localBuffer = new byte[bufferSize];
|
||||
while (true)
|
||||
{
|
||||
int numRead = await memoryStream.ReadAsync(localBuffer, 0, localBuffer.Length);
|
||||
if (numRead <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
await stdIn.WriteAsync(localBuffer, 0, numRead);
|
||||
}
|
||||
await stdIn.FlushAsync();
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new IOException($"Copy command failed: {ex.Message}");
|
||||
}
|
||||
|
||||
using StreamReader streamReader = new StreamReader(stdError);
|
||||
while (streamReader.EndOfStream == false)
|
||||
{
|
||||
string error = await streamReader.ReadToEndAsync();
|
||||
throw new IOException($"Copy command failed: {error}");
|
||||
}
|
||||
});
|
||||
|
||||
string destinationFolder = GetFolderName(destinationFilePath);
|
||||
|
||||
return await client.NamespacedPodExecAsync(
|
||||
name,
|
||||
@namespace,
|
||||
container,
|
||||
new string[] { "sh", "-c", $"tar xmf - -C {destinationFolder}" },
|
||||
false,
|
||||
handler,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
|
||||
private static string GetFolderName(string filePath)
|
||||
{
|
||||
var folderName = Path.GetDirectoryName(filePath);
|
||||
|
||||
return string.IsNullOrEmpty(folderName) ? "." : folderName;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user