-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlagoon-api.js
More file actions
292 lines (249 loc) · 9.83 KB
/
lagoon-api.js
File metadata and controls
292 lines (249 loc) · 9.83 KB
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
import { exec } from 'child_process';
import { promisify } from 'util';
import chalk from 'chalk';
import { logAction, logError } from './logger';
import fs from 'fs/promises';
import path from 'path';
import os from 'os';
const execAsync = promisify(exec);
// Helper function to execute and log Lagoon commands
export async function execLagoonCommand(command, action = 'Unknown Action') {
console.log(chalk.blue(`Executing: ${chalk.bold(command)}`));
try {
const result = await execAsync(command);
logAction(action, command, 'Success');
return result;
} catch (error) {
logError(action, command, error);
throw error;
}
}
// Get all Lagoon instances from the config
export async function getLagoonInstances() {
try {
const command = 'lagoon config list --output-json';
const { stdout } = await execLagoonCommand(command, 'List Lagoon Instances');
// Parse the JSON output
const configData = JSON.parse(stdout);
// Extract instance names from the JSON data and clean them
const instances = configData.data.map(instance => {
// Extract just the base name without (default)(current) or other annotations
const fullName = instance.name;
// Extract just the base name before any parentheses or whitespace
const baseName = fullName.split(/\s+|\(/).shift().trim();
return baseName;
});
return instances;
} catch (error) {
throw new Error(`Failed to get Lagoon instances: ${error.message}`);
}
}
// Get all projects for a Lagoon instance with full details
export async function getProjectsWithDetails(instance) {
try {
const command = `lagoon -l ${instance} list projects --output-json`;
const { stdout } = await execLagoonCommand(command, `List Projects for ${instance}`);
// Parse the JSON output
const projectsData = JSON.parse(stdout);
// Return the full project data
return projectsData.data;
} catch (error) {
throw new Error(`Failed to get projects for instance ${instance}: ${error.message}`);
}
}
// Get all projects for a Lagoon instance
export async function getProjects(instance) {
try {
const command = `lagoon -l ${instance} list projects --output-json`;
const { stdout } = await execLagoonCommand(command, `List Projects for ${instance}`);
// Parse the JSON output
const projectsData = JSON.parse(stdout);
// Extract project names from the JSON data
const projects = projectsData.data.map(project => project.projectname);
return projects;
} catch (error) {
throw new Error(`Failed to get projects for instance ${instance}: ${error.message}`);
}
}
// Get all environments for a project
export async function getEnvironments(instance, project) {
try {
const command = `lagoon -l ${instance} -p ${project} list environments --output-json`;
const { stdout } = await execLagoonCommand(command, `List Environments for ${project}`);
// Parse the JSON output
const environmentsData = JSON.parse(stdout);
// Extract environment names from the JSON data
const environments = environmentsData.data.map(env => env.name);
return environments;
} catch (error) {
throw new Error(`Failed to get environments for project ${project}: ${error.message}`);
}
}
// Get all users for a project
export async function getUsers(instance, project) {
try {
const command = `lagoon -l ${instance} -p ${project} list all-users`;
const { stdout } = await execLagoonCommand(command, `List Users for ${project}`);
const lines = stdout.split('\n').filter(line => line.trim() !== '');
// Skip the header line and extract user names
const users = lines.slice(1).map(line => {
const parts = line.split('|').map(part => part.trim());
return parts[0]; // First column is the user name
});
return users;
} catch (error) {
throw new Error(`Failed to get users for project ${project}: ${error.message}`);
}
}
// Delete an environment
export async function deleteEnvironment(instance, project, environment) {
// Check if environment is protected
if (
environment === 'production' ||
environment === 'master' ||
environment === 'develop' ||
environment.startsWith('project/')
) {
throw new Error(`Cannot delete protected environment: ${environment}`);
}
try {
const command = `lagoon -l ${instance} -p ${project} delete environment --environment ${environment} --force --output-json`;
// response if successful is a JSON {"result":"success"}
const { stdout } = await execLagoonCommand(command, `Delete Environment ${environment} from ${project}`);
const response = JSON.parse(stdout);
if (response.result === 'success') {
console.log(chalk.green(`Environment ${environment} deleted successfully`));
return true;
} else {
throw new Error(`Failed to delete environment ${environment}: ${response}`);
}
} catch (error) {
throw new Error(`Failed to delete environment ${environment}: ${error.message}`);
}
}
// Generate login link for an environment
export async function generateLoginLink(instance, project, environment) {
// Check if environment is protected
if (environment === 'production' || environment === 'master') {
throw new Error(`Cannot generate login link for protected environment: ${environment}`);
}
try {
const command = `lagoon ssh -l ${instance} -p ${project} -e ${environment} -C "drush user:unblock --uid=1 && drush uli"`;
const { stdout } = await execLagoonCommand(command, `Generate Login Link for ${environment} in ${project}`);
return stdout.trim();
} catch (error) {
throw new Error(`Failed to generate login link for environment ${environment}: ${error.message}`);
}
}
// Helper function to convert git URL to GitHub URL
export function gitUrlToGithubUrl(gitUrl) {
// Handle SSH URLs like git@github.com:org/repo.git
if (gitUrl.startsWith('git@github.com:')) {
const path = gitUrl.replace('git@github.com:', '').replace('.git', '');
return `https://github.com/${path}`;
} else if (gitUrl.includes('github.com')) {
return gitUrl.replace('.git', '');
}
// Return null if not a GitHub URL
return null;
}
// Helper function to extract PR number from environment name
export function extractPrNumber(environmentName) {
const match = environmentName.match(/^pr-(\d+)$/i);
return match ? match[1] : null;
}
// Clear Drupal cache for an environment
export async function clearDrupalCache(instance, project, environment) {
try {
const command = `lagoon ssh -l ${instance} -p ${project} -e ${environment} -C "drush cr"`;
const { stdout } = await execLagoonCommand(command, `Clear Cache for ${environment} in ${project}`);
return stdout.trim();
} catch (error) {
throw new Error(`Failed to clear cache for environment ${environment}: ${error.message}`);
}
}
// Helper function to create a temporary directory for git operations
async function createTempDir() {
const tempDir = path.join(os.tmpdir(), `lagoon-cli-wrapper-${Date.now()}`);
await fs.mkdir(tempDir, { recursive: true });
return tempDir;
}
// Helper function to clone a git repository
async function cloneRepository(gitUrl, directory) {
try {
const command = `git clone --bare ${gitUrl} ${directory}`;
await execAsync(command);
return true;
} catch (error) {
logError('Clone Repository', command, error);
throw new Error(`Failed to clone repository: ${error.message}`);
}
}
// Helper function to list branches in a git repository
async function listBranches(directory) {
try {
const command = `cd ${directory} && git branch -r`;
const { stdout } = await execAsync(command);
// Parse the branches from the output
return stdout
.split('\n')
.map(branch => branch.trim())
.filter(branch => branch && !branch.includes('HEAD'))
.map(branch => branch.replace('origin/', ''));
} catch (error) {
logError('List Branches', command, error);
throw new Error(`Failed to list branches: ${error.message}`);
}
}
// Get all branches from a git repository
export async function getGitBranches(gitUrl) {
try {
if (!gitUrl) {
throw new Error('Git URL not provided or invalid');
}
// Create a temporary directory
const tempDir = await createTempDir();
try {
// Clone the repository
await cloneRepository(gitUrl, tempDir);
// List branches
const branches = await listBranches(tempDir);
// Clean up temporary directory
await fs.rm(tempDir, { recursive: true, force: true });
return branches;
} catch (error) {
// Make sure to clean up even if an error occurs
try {
await fs.rm(tempDir, { recursive: true, force: true });
} catch (cleanupError) {
console.error(`Failed to clean up temporary directory: ${cleanupError.message}`);
}
throw error;
}
} catch (error) {
throw new Error(`Failed to get git branches: ${error.message}`);
}
}
// Deploy a branch to Lagoon
export async function deployBranch(instance, project, branch) {
try {
// Validate branch name to prevent command injection
if (!/^[a-zA-Z0-9_.-]+$/.test(branch)) {
throw new Error('Invalid branch name. Branch names must contain only alphanumeric characters, underscores, hyphens, and periods.');
}
const command = `lagoon -l ${instance} -p ${project} deploy branch --branch ${branch} --output-json`;
const { stdout } = await execLagoonCommand(command, `Deploy Branch ${branch} to ${project}`);
// Parse the JSON response
const response = JSON.parse(stdout);
if (response.result === 'success') {
return {
success: true,
message: `Branch ${branch} is being deployed to ${project}`
};
} else {
throw new Error(`Failed to deploy branch ${branch}: ${JSON.stringify(response)}`);
}
} catch (error) {
throw new Error(`Failed to deploy branch ${branch}: ${error.message}`);
}
}