Skip to content

Commit d59f4da

Browse files
lazarkrstictg123
andauthored
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 <[email protected]> * File names as command line args, default encoding * command line args Co-authored-by: Boshi Lian <[email protected]>
1 parent a361f2d commit d59f4da

File tree

2 files changed

+137
-0
lines changed

2 files changed

+137
-0
lines changed

examples/cp/Cp.cs

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
using System;
2+
using System.IO;
3+
using System.Threading.Tasks;
4+
using k8s;
5+
using ICSharpCode.SharpZipLib.Tar;
6+
using System.Threading;
7+
using System.Linq;
8+
using System.Text;
9+
10+
namespace cp
11+
{
12+
internal class Cp
13+
{
14+
private static IKubernetes client;
15+
16+
private static async Task Main(string[] args)
17+
{
18+
var config = KubernetesClientConfiguration.BuildConfigFromConfigFile();
19+
client = new Kubernetes(config);
20+
21+
22+
var pods = client.CoreV1.ListNamespacedPod("default", null, null, null, $"job-name=upload-demo");
23+
var pod = pods.Items.First();
24+
25+
await CopyFileToPodAsync(pod.Metadata.Name, "default", "upload-demo", args[0], $"home/{args[1]}");
26+
27+
}
28+
29+
30+
31+
32+
private static void ValidatePathParameters(string sourcePath, string destinationPath)
33+
{
34+
if (string.IsNullOrWhiteSpace(sourcePath))
35+
{
36+
throw new ArgumentException($"{nameof(sourcePath)} cannot be null or whitespace");
37+
}
38+
39+
if (string.IsNullOrWhiteSpace(destinationPath))
40+
{
41+
throw new ArgumentException($"{nameof(destinationPath)} cannot be null or whitespace");
42+
}
43+
44+
}
45+
46+
public static async Task<int> CopyFileToPodAsync(string name, string @namespace, string container, string sourceFilePath, string destinationFilePath, CancellationToken cancellationToken = default(CancellationToken))
47+
{
48+
// All other parameters are being validated by MuxedStreamNamespacedPodExecAsync called by NamespacedPodExecAsync
49+
ValidatePathParameters(sourceFilePath, destinationFilePath);
50+
51+
// The callback which processes the standard input, standard output and standard error of exec method
52+
var handler = new ExecAsyncCallback(async (stdIn, stdOut, stdError) =>
53+
{
54+
var fileInfo = new FileInfo(destinationFilePath);
55+
try
56+
{
57+
using (var memoryStream = new MemoryStream())
58+
{
59+
using (var inputFileStream = File.OpenRead(sourceFilePath))
60+
using (var tarOutputStream = new TarOutputStream(memoryStream, Encoding.Default))
61+
{
62+
tarOutputStream.IsStreamOwner = false;
63+
64+
var fileSize = inputFileStream.Length;
65+
var entry = TarEntry.CreateTarEntry(fileInfo.Name);
66+
67+
entry.Size = fileSize;
68+
69+
tarOutputStream.PutNextEntry(entry);
70+
await inputFileStream.CopyToAsync(tarOutputStream);
71+
tarOutputStream.CloseEntry();
72+
}
73+
74+
memoryStream.Position = 0;
75+
76+
const int bufferSize = 31 * 1024 * 1024; // must be lower than 32 * 1024 * 1024
77+
byte[] localBuffer = new byte[bufferSize];
78+
while (true)
79+
{
80+
int numRead = await memoryStream.ReadAsync(localBuffer, 0, localBuffer.Length);
81+
if (numRead <= 0)
82+
{
83+
break;
84+
}
85+
await stdIn.WriteAsync(localBuffer, 0, numRead);
86+
}
87+
await stdIn.FlushAsync();
88+
}
89+
90+
}
91+
catch (Exception ex)
92+
{
93+
throw new IOException($"Copy command failed: {ex.Message}");
94+
}
95+
96+
using StreamReader streamReader = new StreamReader(stdError);
97+
while (streamReader.EndOfStream == false)
98+
{
99+
string error = await streamReader.ReadToEndAsync();
100+
throw new IOException($"Copy command failed: {error}");
101+
}
102+
});
103+
104+
string destinationFolder = GetFolderName(destinationFilePath);
105+
106+
return await client.NamespacedPodExecAsync(
107+
name,
108+
@namespace,
109+
container,
110+
new string[] { "sh", "-c", $"tar xmf - -C {destinationFolder}" },
111+
false,
112+
handler,
113+
cancellationToken);
114+
}
115+
116+
117+
private static string GetFolderName(string filePath)
118+
{
119+
var folderName = Path.GetDirectoryName(filePath);
120+
121+
return string.IsNullOrEmpty(folderName) ? "." : folderName;
122+
}
123+
124+
125+
}
126+
}

examples/cp/cp.csproj

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<PackageReference Include="SharpZipLib" Version="1.3.3" />
9+
</ItemGroup>
10+
11+
</Project>

0 commit comments

Comments
 (0)