-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathProgram.cs
134 lines (117 loc) · 5.54 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
namespace AutoDockerhubPull
{
class Program
{
static async Task Main(string[] args)
{
string username = args[0];
string password = args[1];
string organization = args[2];
string token = await GetToken(username, password);
IReadOnlyList<string> repositories = await GetRepositories(organization, token);
IEnumerable<Task<IEnumerable<string>>> getImagesTasks = repositories.Select(repository => GetImages(organization, repository, token));
IEnumerable<string> images = (await Task.WhenAll(getImagesTasks)).SelectMany(image => image);
Console.WriteLine(string.Join('\n', images));
GeneratePipelineYML(images);
}
/// <summary>
/// 取得用於存取 dockerhub api 的 token
/// </summary>
/// <param name="username">dockerhub 帳號</param>
/// <param name="password">dockerhub 密碼</param>
/// <returns></returns>
private static async Task<string> GetToken(string username, string password)
{
Dictionary<string, string> body = new Dictionary<string, string>()
{
{ "username", username },
{ "password", password }
};
Uri tokenUrl = new Uri($"https://hub.docker.com/v2/users/login/");
var formData = new FormUrlEncodedContent(body);
HttpClient tokenClient = HttpClientFactory.Create();
var tokenBuffer = await tokenClient.PostAsync(tokenUrl, formData);
string tokenJson = await tokenBuffer.Content.ReadAsStringAsync();
JObject jObject = JObject.Parse(tokenJson);
if (jObject.Property("token") is null)
throw new Exception("get token failed.");
return jObject["token"].ToString();
}
/// <summary>
/// 取得組織內的所有存放庫
/// </summary>
/// <param name="organization"> 組織名稱 </param>
/// <param name="token"> 用於存取組織的 token </param>
/// <returns></returns>
private static async Task<IReadOnlyList<string>> GetRepositories(string organization, string token)
{
string nextUri = $"https://hub.docker.com/v2/repositories/{organization}/";
List<string> repositories = new List<string>();
while (!string.IsNullOrEmpty(nextUri))
{
string jsonString = await CallApi(nextUri, token);
JObject jObject = JObject.Parse(jsonString);
if (jObject.Property("detail") != null)
throw new Exception("origin not found.");
nextUri = jObject.Property("next") is null ? string.Empty : jObject["next"].ToString();
repositories.AddRange(jObject["results"].Select(item => item.Value<string>("name")));
}
return repositories;
}
/// <summary>
/// 取得組織內的 image
/// </summary>
/// <param name="organization"> 組織名稱 </param>
/// <param name="repository"> 存放庫名稱 </param>
/// <param name="token"> 用於存取組織的 token </param>
/// <returns></returns>
private static async Task<IEnumerable<string>> GetImages(string organization, string repository, string token)
{
string nextUri = $"https://hub.docker.com/v2/repositories/{organization}/{repository}/tags/";
List<string> tags = new List<string>();
while (!string.IsNullOrEmpty(nextUri))
{
string jsonString = await CallApi(nextUri, token);
JObject jObject = JObject.Parse(jsonString);
if (jObject["count"].ToString() == "0")
throw new Exception("repository not found.");
nextUri = jObject.Property("next") is null ? string.Empty : jObject["next"].ToString();
tags.AddRange(jObject["results"].Select(item => item.Value<string>("name")));
}
return tags.Select(tag => $@"""{organization}/{repository}:{tag}""");
}
/// <summary>
/// 將 images 寫入 run-docker.yml
/// </summary>
/// <param name="images"> 映像檔 </param>
/// <returns></returns>
private static void GeneratePipelineYML(IEnumerable<string> images)
{
string content = File.ReadAllText("./azure-pipelines/run-docker-template.yml");
content = content.Replace("{0}", DateTime.UtcNow.ToString());
content = content.Replace("{1}", string.Join(", ", images));
File.WriteAllText("./azure-pipelines/run-docker.yml", content);
}
/// <summary>
/// 呼叫 dockerhub api 取得 image or image tag
/// </summary>
/// <param name="uri"> api url </param>
/// <param name="token"> 用於存取組織的 token </param>
/// <returns></returns>
private static async Task<string> CallApi(string uri, string token)
{
Uri repositoryUrl = new Uri(uri);
HttpClient repositoryClient = HttpClientFactory.Create();
repositoryClient.DefaultRequestHeaders.Add("Authorization", $"JWT {token}");
var repositoryBuffer = await repositoryClient.GetAsync(repositoryUrl);
return await repositoryBuffer.Content.ReadAsStringAsync();
}
}
}