Line data Source code
1 : /*
2 : deployd_cmd.c
3 : Created by Danny Goossen, Gioxa Ltd on 6/2/17.
4 :
5 : MIT License
6 :
7 : Copyright (c) 2017 deployctl, Gioxa Ltd.
8 :
9 : Permission is hereby granted, free of charge, to any person obtaining a copy
10 : of this software and associated documentation files (the "Software"), to deal
11 : in the Software without restriction, including without limitation the rights
12 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 : copies of the Software, and to permit persons to whom the Software is
14 : furnished to do so, subject to the following conditions:
15 :
16 : The above copyright notice and this permission notice shall be included in all
17 : copies or substantial portions of the Software.
18 :
19 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 : SOFTWARE.
26 :
27 : */
28 :
29 : #include "deployd.h"
30 :
31 :
32 0 : int cmd_tree(void * opaque)
33 : {
34 0 : int exitcode=0;
35 0 : struct trace_Struct *trace=((data_exchange_t *)opaque)->trace;
36 : char command[4096]; // temporary string
37 :
38 0 : cJSON * env_json=((data_exchange_t *)opaque)->env_json;
39 0 : char * dir=cJSON_get_key(env_json, "CI_PROJECT_DIR");
40 :
41 0 : ((data_exchange_t *)opaque)->needenvp=0;
42 :
43 0 : int snres=snprintf((char *)command,4096,"cd %s && tree -I '.git' -hCqFax",dir);
44 0 : if (snres>=4096)
45 : {
46 0 : Write_dyn_trace(trace, red,"ERROR: command exeeds max length\n");
47 0 : exitcode=1;
48 0 : return(exitcode);
49 : }
50 0 : Write_dyn_trace(trace, none,"+ %s \n",command);
51 0 : update_details(trace);
52 0 : debug("cmd: %s\n",command);
53 0 : ((data_exchange_t *)opaque)->shellcommand=command;
54 0 : exitcode=exec_color(opaque);
55 0 : if (exitcode) {debug("ERROR: ls -la\n");}
56 : // check if certs
57 :
58 0 : return(exitcode);
59 : }
60 :
61 0 : int cmd_color_test(void * opaque)
62 : {
63 0 : int exitcode=0;
64 0 : struct trace_Struct *trace=((data_exchange_t *)opaque)->trace;
65 : char command[4096]; // temporary string
66 :
67 :
68 0 : ((data_exchange_t *)opaque)->needenvp=0;
69 : // export TERM=xterm-256color && source ~/.bash_profile &&
70 : //int snres=snprintf((char *)command,4096,"cd %s && tree -hCqcFx",dir);
71 0 : int snres=snprintf((char *)command,4096,"colortest.py");
72 : if (snres>=4096)
73 : {
74 : Write_dyn_trace(trace, red,"ERROR: command exeeds max length\n");
75 : exitcode=1;
76 : return(exitcode);
77 : }
78 0 : Write_dyn_trace(trace, none,"+ %s \n",command);
79 0 : update_details(trace);
80 0 : debug("cmd: %s\n",command);
81 0 : ((data_exchange_t *)opaque)->shellcommand=command;
82 0 : exitcode=exec_color(opaque);
83 0 : if (exitcode) {debug("ERROR: ls -la\n");}
84 :
85 : return(exitcode);
86 : }
87 :
88 0 : int cmd_env(void * opaque)
89 : {
90 0 : int exitcode=0;
91 0 : struct trace_Struct *trace=((data_exchange_t *)opaque)->trace;
92 : char command[4096]; // temporary string
93 :
94 : //cJSON * env_json=((data_exchange_t *)opaque)->env_json;
95 :
96 0 : ((data_exchange_t *)opaque)->needenvp=1;
97 :
98 0 : int snres=snprintf((char *)command,4096,"env");
99 : if (snres>=4096)
100 : {
101 : Write_dyn_trace(trace, red,"ERROR: command exeeds max length\n");
102 : exitcode=1;
103 : return(exitcode);
104 : }
105 0 : Write_dyn_trace(trace, none,"+ %s \n",command);
106 0 : update_details(trace);
107 0 : debug("cmd: %s\n",command);
108 0 : ((data_exchange_t *)opaque)->shellcommand=command;
109 0 : exitcode=exec_color(opaque);
110 0 : if (exitcode) {debug("ERROR: ls -la\n");}
111 : // check if certs
112 0 : update_details(trace);
113 : return(exitcode);
114 : }
115 : /*------------------------------------------------------------------------
116 : * Internal Command : Delete : Delete an environment
117 : *------------------------------------------------------------------------*/
118 13 : int cmd_delete(void * opaque)
119 : {
120 : // feedback buffer
121 13 : int exitcode=0;
122 13 : struct trace_Struct *trace=((data_exchange_t *)opaque)->trace;
123 13 : cJSON * env_json=((data_exchange_t *)opaque)->env_json;
124 13 : parameter_t * param=((data_exchange_t *)opaque)->parameters;
125 : // just to make sure we're at the right position
126 : char * newarg[8];
127 : // no need to set environment for individual commands
128 13 : ((data_exchange_t *)opaque)->needenvp=0;
129 13 : ((data_exchange_t *)opaque)->paramlist=(char **)newarg;
130 : char basePATH[1024];
131 13 : debug("checking environment\n");
132 : // if (cJSON_GetObjectItem(env_json, "CI_PROJECT_PATH_SLUG") && cJSON_GetObjectItem(env_json, "CI_ENVIRONMENT_SLUG")&& cJSON_GetObjectItem(env_json, "CI_PROJECT_DIR") && cJSON_GetObjectItem(env_json, "CI_ENVIRONMENT_NAME") && cJSON_GetObjectItem(env_json, "CI_COMMIT_SHA"))
133 13 : int cnt=0;
134 13 : if ((cnt=check_presence(env_json,
135 : (char *[])
136 13 : {"CI_PROJECT_PATH_SLUG","CI_ENVIRONMENT_SLUG","CI_ENVIRONMENT_NAME","CI_PROJECT_PATH","CI_PROJECT_DIR","CI_COMMIT_SHA","CI_PROJECT_URL",NULL}
137 : , trace)))
138 : {
139 1 : Write_dyn_trace(trace, red,"\nERROR: %d Environment variable(s) Missing\n",cnt);
140 1 : debug("\nERROR: %d Environment variable(s) Missing!!!\n",cnt);
141 1 : exitcode=1;
142 : }
143 : else
144 : {
145 : // inform deployctl of environment deployment
146 12 : debug("Deploy environment :%s\n",cJSON_GetObjectItem(env_json, "CI_ENVIRONMENT_NAME")->valuestring);
147 : //Write_dyn_trace(trace, none,"Deploy environment :%s\n",cJSON_GetObjectItem(env_json, "CI_ENVIRONMENT_NAME")->valuestring);
148 12 : if (validate_key(env_json, "CI_ENVIRONMENT_NAME", "production")==0)
149 : {
150 7 : if (! cJSON_GetObjectItem(env_json, "DEPLOY_DOMAIN"))
151 : { // we got no deploydomain, so make one
152 : // as per : $CI_ENVIRONMENT_SLUG.$CI_PROJECT_PATH_SLUG.$DEPLOY_DOMAIN_APP
153 3 : debug("PRODUCTION deployment, no deploydomain \n" );
154 3 : if(validate_project_path_slug(env_json, trace,1)!=0)
155 : {
156 1 : Write_dyn_trace(trace, red,"Environment not OK!! \n ** \"DEPLOY_DOMAIN\" and/or \"DEPLOY_APP_DOMAIN\" not defined ** \n");
157 1 : exitcode=1;
158 1 : return exitcode;
159 : }
160 : else
161 : {
162 2 : debug("assemble domain\n");
163 2 : char * env_slug=cJSON_get_key(env_json, "CI_ENVIRONMENT_SLUG");
164 2 : char * project_path_slug=cJSON_get_key(env_json, "CI_PROJECT_PATH_SLUG");
165 2 : char * deploy_app_domain=cJSON_get_key(env_json, "DEPLOY_DOMAIN_APP");
166 2 : debug("parts%s.%s.%s\n",env_slug,project_path_slug,deploy_app_domain);
167 :
168 2 : if ((strlen(env_slug)+strlen(project_path_slug)+strlen(deploy_app_domain)+3) > 255)
169 : {
170 1 : debug("ENVIRONMENT/PROJECTPATH/DEPLOYAPP to long\n");
171 1 : Write_dyn_trace(trace, red,"ERROR: ENVIRONMENT/PROJECTPATH/DEPLOYAPP to long\n");
172 1 : exitcode=1;
173 1 : return exitcode;
174 : }
175 :
176 : char deploy_domain[256];
177 1 : sprintf(deploy_domain, "%s.%s.%s",env_slug,project_path_slug,deploy_app_domain);
178 1 : debug("new domain %s\n",deploy_domain);
179 1 : cJSON_AddItemToObject(env_json, "DEPLOY_DOMAIN", cJSON_CreateString(deploy_domain));
180 : }
181 : }
182 5 : sprintf((char *)basePATH,"%s/deploy/domain/%s",param->prefix,cJSON_get_key(env_json, "DEPLOY_DOMAIN"));
183 5 : debug("basePATH=%s\n",basePATH);
184 : }
185 : else
186 : {
187 5 : debug("NOT a production deployment\n");
188 5 : if (! cJSON_GetObjectItem(env_json, "DEPLOY_DOMAIN_APP"))
189 : {
190 1 : debug("DEPLOY_DOMAIN_APP not found\n");
191 1 : Write_dyn_trace(trace, none,"ERROR: Environment not OK, $DEPLOY_APP_DOMAIN not defined\n");
192 1 : exitcode=1;
193 1 : return exitcode;
194 : }
195 4 : if(validate_project_path_slug(env_json, trace,1)!=0)
196 : {
197 1 : Write_dyn_trace(trace, red,"ERR: Environment not OK!! \n");
198 1 : exitcode=1;
199 1 : return exitcode;
200 : }
201 3 : sprintf((char *)basePATH,"%s/deploy/sites/%s/%s",param->prefix,cJSON_get_key(env_json, "CI_PROJECT_PATH_SLUG"),cJSON_get_key(env_json, "CI_ENVIRONMENT_SLUG") );
202 : }
203 : //rm
204 8 : if (check_namespace(opaque, basePATH)!=0)
205 : {
206 1 : Write_dyn_trace(trace, red,"\n ERROR: Namespace belows to another Project!! \n");
207 1 : exitcode=1;
208 1 : return exitcode;
209 : }
210 :
211 7 : newarg[0]="/bin/rm";
212 7 : newarg[1]="-rf";
213 7 : newarg[2]=basePATH;
214 7 : newarg[3]=NULL;
215 7 : Write_dyn_trace(trace, none,"+ rm deployment \n");
216 7 : debug("cmd: %s %s %s \n",newarg[0],newarg[1],newarg[2]);
217 7 : exitcode=cmd_exec(opaque);
218 7 : if (exitcode) {debug("Failed exec rmdir %s\n",newarg[2]);return exitcode;}
219 : }
220 : // TODO
221 8 : return exitcode;
222 : }
223 :
224 : /*------------------------------------------------------------------------
225 : * Internal Command : config https, configures https (letsencrypt)
226 : *------------------------------------------------------------------------*/
227 0 : int cmd_conf_https(void * opaque)
228 : {
229 : // feedback buffer
230 0 : int exitcode=0;
231 0 : struct trace_Struct *trace=((data_exchange_t *)opaque)->trace;
232 : // env json
233 0 : cJSON * env_json=((data_exchange_t *)opaque)->env_json;
234 0 : parameter_t * param=((data_exchange_t *)opaque)->parameters;
235 : char * newarg[11];
236 : // no need to set environment for individual commands
237 0 : ((data_exchange_t *)opaque)->needenvp=0;
238 0 : ((data_exchange_t *)opaque)->paramlist=(char **)newarg;
239 : char basePATH[1024];
240 : char baseHREF[1024];
241 : struct stat st;
242 0 : debug("checking environment\n");
243 0 : int cnt=0;
244 0 : if ((cnt=check_presence(env_json,
245 : (char *[])
246 0 : {"CI_PROJECT_PATH_SLUG","CI_ENVIRONMENT_SLUG","CI_ENVIRONMENT_NAME","CI_PROJECT_PATH","GITLAB_USER_EMAIL",NULL}
247 : , trace)))
248 : {
249 0 : Write_dyn_trace(trace, none,"ERROR: %d Environment variable(s) Missing\n",cnt);
250 0 : debug("\nERROR: %d Environment variable(s) Missing!!!\n",cnt);
251 0 : exitcode=1;
252 : }
253 : else
254 : {
255 : // inform deployctl of environment deployment
256 0 : debug("Deploy environment :%s\n",cJSON_get_key(env_json, "CI_ENVIRONMENT_NAME"));
257 : //Write_dyn_trace(trace, none,"Deploy environment :%s\n",cJSON_get_key(env_json, "CI_ENVIRONMENT_NAME"));
258 0 : debug("check CI_ENV\n");
259 0 : if (validate_key(env_json, "CI_ENVIRONMENT_NAME", "production")==0)
260 : {
261 0 : debug("PRODUCTION deployment=> OK\n");
262 0 : if (! cJSON_GetObjectItem(env_json, "DEPLOY_DOMAIN"))
263 : { // we got no deploydomain, so make one
264 : // as per : $CI_ENVIRONMENT_SLUG.$CI_PROJECT_PATH_SLUG.$DEPLOY_DOMAIN_APP
265 0 : if(validate_project_path_slug(env_json, trace,1)!=0)
266 : {
267 0 : Write_dyn_trace(trace, red,"Environment not OK!! \n ** \"DEPLOY_DOMAIN\" and/or \"DEPLOY_APP_DOMAIN\" not defined ** \n");
268 0 : exitcode=1;
269 0 : return exitcode;
270 : }
271 : else
272 : {
273 0 : char * env_slug=cJSON_get_key(env_json, "CI_ENVIRONMENT_SLUG");
274 0 : char * project_path_slug=cJSON_get_key(env_json, "CI_PROJECT_PATH_SLUG");
275 0 : char * deploy_app_domain=cJSON_get_key(env_json, "DEPLOY_DOMAIN_APP");
276 0 : char * deploy_domain=calloc(1,strlen(env_slug)+strlen(project_path_slug)+strlen(deploy_app_domain)+3);
277 0 : sprintf(deploy_domain, "%s.%s.%s",env_slug,project_path_slug,deploy_app_domain);
278 0 : cJSON_AddItemToObject(env_json, "DEPLOY_DOMAIN", cJSON_CreateString(deploy_domain));
279 : }
280 : }
281 0 : sprintf(baseHREF,"http://%s",cJSON_get_key(env_json, "DEPLOY_DOMAIN"));
282 0 : sprintf((char *)basePATH,"%s/deploy/domain/%s",param->prefix,cJSON_get_key(env_json, "DEPLOY_DOMAIN"));
283 : }
284 : else
285 : {
286 0 : debug("config-https only for production environment\n");
287 0 : Write_dyn_trace(trace, red,"\n ERROR: config-https only for production environment\n");
288 0 : exitcode=1;
289 0 : return exitcode;
290 : }
291 : // check domaindir
292 0 : if(stat(basePATH,&st) != 0)
293 : {
294 : // deploydir not present no point to continue
295 0 : debug("ERROR: Deploy dir %s not present\n",basePATH);
296 0 : Write_dyn_trace(trace, red,"\n ERROR: no deployment present\n");
297 0 : exitcode=1;
298 0 : return exitcode;
299 : }
300 : //Write_dyn_trace(trace, none,"Deploy environment :%s\n",cJSON_get_key(env_json, "CI_ENVIRONMENT_NAME"));
301 : // now check if dir exist, if so check the "CI_PROJECT_URL" !!!
302 0 : if (check_namespace(opaque, basePATH)!=0)
303 : {
304 0 : Write_dyn_trace(trace, red,"\n ERROR: Namespace belows to another Project!! \n");
305 0 : exitcode=1;
306 0 : return exitcode;
307 : }
308 : // check if dns points to this instance for this url
309 0 : exitcode= url_check(opaque, basePATH,baseHREF);
310 0 : if (exitcode)
311 : {
312 0 : debug("ERR: url check\n");
313 0 : return exitcode;
314 : }
315 0 : update_details(trace);
316 0 : debug("start letsencript\n");
317 : // check if letsencript config exists, if not create new cert
318 0 : exitcode=letsencrypt(opaque,cJSON_get_key(env_json, "DEPLOY_DOMAIN"),cJSON_get_key(env_json, "GITLAB_USER_EMAIL"));
319 : // write https
320 0 : if (!exitcode)
321 : {
322 0 : exitcode= write_http_config(opaque,1,basePATH,cJSON_get_key(env_json, "DEPLOY_DOMAIN"));
323 0 : if (exitcode){debug("Failed create http config\n");return exitcode;}
324 0 : exitcode= verify_http_config(opaque);
325 0 : if (exitcode)
326 : {
327 0 : debug("Failed nginx -t \n");
328 0 : delete_http_config(opaque,basePATH);
329 :
330 0 : return exitcode;
331 : }
332 0 : else exitcode=reload_http_config(opaque);
333 : }
334 0 : else debug("ERR: let's encrypt failed\n");
335 0 : update_details(trace);
336 : }
337 0 : return exitcode;
338 : }
339 :
340 : /*------------------------------------------------------------------------
341 : * Internal Command : static : filter the env and rsync project/public to public
342 : *------------------------------------------------------------------------*/
343 16 : int cmd_static(void * opaque)
344 : {
345 : // feedback buffer
346 16 : int exitcode=0;
347 16 : struct trace_Struct *trace=((data_exchange_t *)opaque)->trace;
348 : // env json
349 16 : cJSON * env_json=((data_exchange_t *)opaque)->env_json;
350 : char * newarg[8];
351 : // no need to set environment for individual commands
352 16 : ((data_exchange_t *)opaque)->needenvp=0;
353 16 : ((data_exchange_t *)opaque)->paramlist=(char **)newarg;
354 16 : parameter_t * param=((data_exchange_t *)opaque)->parameters;
355 : char var_arg1_string[1024];
356 : // char * var_dest_dir_string[1024];
357 : char basePATH[1024];
358 : char baseHREF[1024];
359 : char pubPATH[1024];
360 16 : int deploy_production=0;
361 : // setdebug();
362 16 : debug("checking environment\n");
363 16 : int cnt=0;
364 16 : if ((cnt=check_presence(env_json,
365 : (char *[])
366 16 : {"CI_PROJECT_PATH_SLUG","CI_ENVIRONMENT_SLUG","CI_ENVIRONMENT_NAME","CI_PROJECT_PATH","CI_PROJECT_DIR","CI_COMMIT_SHA","CI_PROJECT_URL",NULL}
367 : , trace)))
368 : {
369 1 : Write_dyn_trace(trace, red,"ERROR: %d Environment variable(s) Missing\n",cnt);
370 1 : debug("\nERROR: %d Environment variable(s) Missing!!!\n",cnt);
371 1 : exitcode=1;
372 : }
373 : else
374 : {
375 : // inform deployctl of environment deployment
376 15 : debug("Deploy environment :%s\n",cJSON_get_key(env_json, "CI_ENVIRONMENT_NAME"));
377 :
378 15 : debug("wrote env\n");
379 15 : if (validate_key(env_json, "CI_ENVIRONMENT_NAME", "production")==0)
380 : {
381 10 : debug("validate_key\n");
382 10 : if (! cJSON_GetObjectItem(env_json, "DEPLOY_DOMAIN"))
383 : { // we got no deploydomain, so make one
384 : // as per : $CI_ENVIRONMENT_SLUG.$CI_PROJECT_PATH_SLUG.$DEPLOY_DOMAIN_APP
385 : //debug("PRODUCTION deployment, no deploydomain and slugok=%d \n",(validate_project_path_slug(opaque, trace)!=0) );
386 4 : if(validate_project_path_slug(env_json, trace,1)!=0)
387 : {
388 1 : Write_dyn_trace(trace, none,"Environment not OK!! \n ** \"DEPLOY_DOMAIN\" and/or \"DEPLOY_APP_DOMAIN\" not defined ** \n");
389 1 : exitcode=1;
390 1 : return exitcode;
391 : }
392 : else
393 : {
394 3 : debug("assemble domain\n");
395 3 : char * env_slug=cJSON_get_key(env_json, "CI_ENVIRONMENT_SLUG");
396 3 : char * project_path_slug=cJSON_get_key(env_json, "CI_PROJECT_PATH_SLUG");
397 3 : char * deploy_app_domain=cJSON_get_key(env_json, "DEPLOY_DOMAIN_APP");
398 3 : debug("parts%s.%s.%s\n",env_slug,project_path_slug,deploy_app_domain);
399 : // TODO change to one function
400 3 : if ((strlen(env_slug)+strlen(project_path_slug)+strlen(deploy_app_domain)+3) > 255)
401 : {
402 1 : debug("ENVIRONMENT/PROJECTPATH/DEPLOYAPP to long\n");
403 1 : Write_dyn_trace(trace, none,"ERR: ENVIRONMENT/PROJECTPATH/DEPLOYAPP to long\n");
404 1 : exitcode=1;
405 1 : return exitcode;
406 : }
407 : // TODO check others, need to be static, no malloc => mem leaks
408 : char deploy_domain[256];
409 2 : sprintf(deploy_domain, "%s.%s.%s",env_slug,project_path_slug,deploy_app_domain);
410 2 : debug("new domain %s\n",deploy_domain);
411 2 : cJSON_AddItemToObject(env_json, "DEPLOY_DOMAIN", cJSON_CreateString(deploy_domain));
412 : }
413 : }
414 8 : deploy_production=1;
415 8 : sprintf((char *)basePATH,"%s/deploy/domain/%s",param->prefix,cJSON_get_key(env_json, "DEPLOY_DOMAIN"));
416 8 : sprintf(baseHREF,"http://%s",cJSON_get_key(env_json, "DEPLOY_DOMAIN"));
417 : }
418 : else
419 : {
420 5 : debug("NOT a production deployment\n");
421 5 : deploy_production=0;
422 5 : if (! cJSON_GetObjectItem(env_json, "DEPLOY_DOMAIN_APP"))
423 : {
424 1 : debug("DEPLOY_DOMAIN_APP not found\n");
425 1 : Write_dyn_trace(trace, none,"ERR: Environment not OK, $DEPLOY_APP_DOMAIN not defined\n");
426 1 : exitcode=1;
427 1 : return exitcode;
428 : }
429 4 : if(validate_project_path_slug(env_json, trace,1)!=0)
430 : {
431 1 : Write_dyn_trace(trace, none,"ERR: Environment not OK!! \n");
432 1 : exitcode=1;
433 1 : return exitcode;
434 : }
435 3 : debug("assemble domain\n");
436 3 : char * env_slug=cJSON_get_key(env_json, "CI_ENVIRONMENT_SLUG");
437 3 : char * project_path_slug=cJSON_get_key(env_json, "CI_PROJECT_PATH_SLUG");
438 3 : char * deploy_app_domain=cJSON_get_key(env_json, "DEPLOY_DOMAIN_APP");
439 3 : debug("parts%s.%s.%s\n",env_slug,project_path_slug,deploy_app_domain);
440 3 : debug("paramprefix=%s\n",param->prefix);
441 3 : sprintf((char *)basePATH,"%s/deploy/sites/%s/%s",param->prefix,cJSON_get_key(env_json, "CI_PROJECT_PATH_SLUG"),cJSON_get_key(env_json, "CI_ENVIRONMENT_SLUG") );
442 3 : sprintf(baseHREF,"http://%s.%s.%s",cJSON_get_key(env_json, "CI_ENVIRONMENT_SLUG"),cJSON_get_key(env_json, "CI_PROJECT_PATH_SLUG"), cJSON_get_key(env_json, "DEPLOY_DOMAIN_APP"));
443 : char deploy_domain[256];
444 3 : sprintf(deploy_domain, "%s.%s.%s",env_slug,project_path_slug,deploy_app_domain);
445 3 : debug("new domain %s\n",deploy_domain);
446 3 : if (cJSON_get_key(env_json,"DEPLOY_DOMAIN"))
447 2 : cJSON_ReplaceItemInObject(env_json, "DEPLOY_DOMAIN", cJSON_CreateString(deploy_domain));
448 : else
449 1 : cJSON_AddItemToObject(env_json, "DEPLOY_DOMAIN", cJSON_CreateString(deploy_domain));
450 3 : debug("basepath=%s\n",basePATH);
451 : }
452 : // now check if dir exist, if so check the "CI_PROJECT_URL" !!!
453 11 : if (check_namespace(opaque, basePATH)!=0)
454 : {
455 2 : Write_dyn_trace(trace, none,"ERR: Namespace belows to another Project!! \n");
456 2 : exitcode=1;
457 2 : return exitcode;
458 : }
459 :
460 : // need pubdir
461 9 : sprintf(pubPATH,"%s/public",basePATH);
462 9 : debug("pubpath=%s, %d\n",pubPATH,exitcode);
463 :
464 9 : _mkdir(NULL,pubPATH);
465 :
466 9 : Write_dyn_trace(trace, none,"+ mkdir public \n");
467 : //if (deploy_production)
468 : {
469 9 : exitcode= write_http_config(opaque,0,basePATH,cJSON_get_key(env_json, "DEPLOY_DOMAIN"));
470 9 : if (exitcode){debug("Failed create http config\n");return exitcode;}
471 8 : exitcode= verify_http_config(opaque);
472 8 : if (exitcode)
473 : {
474 1 : debug("Failed nginx -t \n");
475 1 : delete_http_config(opaque,basePATH);
476 :
477 1 : return exitcode;
478 : }
479 7 : else exitcode=reload_http_config(opaque);
480 : }
481 :
482 : // check if dns points to this instance for this url
483 7 : if (!exitcode) exitcode= url_check(opaque, basePATH,baseHREF);
484 : // remove pubdir
485 7 : _rmdir(NULL ,pubPATH );
486 7 : debug("starting with publish paths, exitcode %d\n",exitcode);
487 : // replace with our wishes
488 7 : if (!exitcode)
489 : {
490 : cJSON * dep_path;
491 8 : cJSON_ArrayForEach(dep_path, cJSON_GetObjectItem(env_json, "DEPLOY_PUBLISH_PATH"))
492 : {
493 4 : char * source=dep_path->child->valuestring;
494 4 : char * target=dep_path->child->string;
495 4 : char * dir=NULL;
496 4 : split_path_file_2_path(&dir,target);
497 4 : _mkdir(dir,pubPATH);
498 4 : debug("s=%s, t=%s,tdir=%s\n",source,target,dir);
499 4 : if (dir) free(dir);
500 4 : if (!exitcode)
501 : {
502 : // rsync
503 4 : newarg[0]="/bin/sh";
504 4 : newarg[1]="-c";
505 4 : newarg[2]=(char *)var_arg1_string;
506 4 : sprintf((char *)newarg[2],"/usr/bin/rsync -r %s%s %s%s",cJSON_get_key(env_json, "CI_PROJECT_DIR"),source,pubPATH,target);
507 4 : newarg[3]=NULL;
508 4 : Write_dyn_trace(trace, none,"+ rsync ");
509 4 : Write_dyn_trace_pad(trace, cyan,75-8,"%s -> %s", source,target);
510 4 : debug("cmd: %s %s %s\n",newarg[0],newarg[1],newarg[2]);
511 4 : exitcode=cmd_exec(opaque);
512 4 : if (exitcode)
513 : {
514 0 : debug("Failed exec rsync %s: %s\n",newarg[2],trace);
515 0 : Write_dyn_trace(trace, red,"\n [FAILED]\n");
516 0 : return exitcode;
517 : }
518 4 : else Write_dyn_trace(trace, green,"[OK]\n");
519 : }
520 : }
521 : }
522 7 : if (!exitcode)
523 : {
524 4 : exitcode=write_namespace(opaque, basePATH);
525 4 : if (exitcode) debug("Failed to write_namespace\n");
526 : }
527 7 : if (!exitcode && deploy_production && validate_key(env_json, "DEPLOY_CONFIG_HTTPS","True" )==0)
528 : {
529 : //config https
530 :
531 0 : debug("start letsencript\n");
532 : // check if letsencript config exists, if not create new cert
533 0 : exitcode=letsencrypt(opaque,cJSON_get_key(env_json, "DEPLOY_DOMAIN"),cJSON_get_key(env_json, "GITLAB_USER_EMAIL"));
534 : // write https
535 0 : if (!exitcode)
536 : {
537 0 : exitcode= write_http_config(opaque,1,basePATH,cJSON_get_key(env_json, "DEPLOY_DOMAIN"));
538 0 : if (exitcode){debug("Failed create http config\n");return exitcode;}
539 0 : exitcode= verify_http_config(opaque);
540 0 : if (exitcode)
541 : {
542 0 : debug("Failed nginx -t \n");
543 0 : delete_http_config(opaque,basePATH);
544 :
545 0 : return exitcode;
546 : }
547 0 : else exitcode=reload_http_config(opaque);
548 : }
549 0 : else debug("ERR: let's encrypt failed\n");
550 0 : update_details(trace);
551 : }
552 : }
553 8 : return exitcode;
554 : }
555 :
556 : /*------------------------------------------------------------------------
557 : * Internal Command : Release : filter the env, create release and rsync
558 : *------------------------------------------------------------------------*/
559 20 : int cmd_release(void * opaque)
560 : {
561 : // feedback buffer
562 20 : int exitcode=0;
563 20 : struct trace_Struct *trace=((data_exchange_t *)opaque)->trace;
564 : // env json
565 20 : cJSON * env_json=((data_exchange_t *)opaque)->env_json;
566 : char * newarg[8];
567 : // no need to set environment for individual commands
568 20 : ((data_exchange_t *)opaque)->needenvp=0;
569 20 : ((data_exchange_t *)opaque)->paramlist=(char **)newarg;
570 20 : parameter_t * param=((data_exchange_t *)opaque)->parameters;
571 : char var_arg1_string[1024];
572 : char var_arg2_string[1024];
573 : // char * var_dest_dir_string[1024];
574 20 : int deploy_production=0;
575 20 : debug("checking environment\n");
576 : char basePATH[1024];
577 : char baseHREF[1024];
578 : char tagPATH[1024];
579 : char tagHREF[1024];
580 : char subPATH[1024];
581 20 : char * build_ref_slug=NULL;
582 20 : int cnt=0;
583 :
584 20 : if ((cnt=check_presence(env_json,
585 : (char *[])
586 20 : {"CI_PROJECT_PATH_SLUG","CI_ENVIRONMENT_SLUG","CI_ENVIRONMENT_NAME","CI_PROJECT_PATH","CI_PROJECT_DIR","CI_COMMIT_SHA","CI_COMMIT_REF_SLUG","CI_PROJECT_URL","CI_JOB_TOKEN","CI_PROJECT_ID",NULL}
587 : , trace)))
588 : {
589 1 : Write_dyn_trace(trace, red,"ERROR: %d Environment variable(s) Missing\n",cnt);
590 1 : debug("\nERROR: %d Environment variable(s) Missing!!!\n",cnt);
591 1 : exitcode=1;
592 : }
593 : else
594 : {
595 : // inform deployctl of environment deployment
596 19 : debug("Deploy environment :%s\n",cJSON_get_key(env_json, "CI_ENVIRONMENT_NAME"));
597 : //Write_dyn_trace(trace, none,"Deploy environment :%s\n",cJSON_GetObjectItem(env_json, "CI_ENVIRONMENT_NAME")->valuestring);
598 19 : build_ref_slug=cJSON_get_key(env_json, "CI_COMMIT_REF_SLUG");
599 19 : if (validate_key(env_json, "CI_ENVIRONMENT_NAME", "production")==0)
600 : {
601 14 : debug("PRODUCTION deployment\n");
602 14 : deploy_production=1;
603 14 : if (!cJSON_get_key(env_json,"CI_COMMIT_TAG"))
604 : {
605 1 : Write_dyn_trace(trace, none,"Production release without a release TAG not OK!! \n");
606 1 : exitcode=1;
607 1 : return exitcode;
608 : }
609 13 : if (! cJSON_GetObjectItem(env_json, "DEPLOY_DOMAIN"))
610 : { // we got no deploydomain, so make one
611 : // as per : $CI_ENVIRONMENT_SLUG.$CI_PROJECT_PATH_SLUG.$DEPLOY_DOMAIN_APP
612 :
613 3 : debug("\nNo Deploy demain:\n");
614 3 : if(validate_project_path_slug(env_json, trace,1)!=0)
615 : {
616 1 : debug("no valid project path\n");
617 1 : Write_dyn_trace(trace, red,"Environment not OK!! \n ** \"DEPLOY_DOMAIN\" and/or \"DEPLOY_APP_DOMAIN\" not defined ** \n");
618 1 : exitcode=1;
619 1 : return exitcode;
620 : }
621 : else
622 : {
623 2 : debug("extracting new domain\n");
624 2 : char * env_slug=cJSON_get_key(env_json, "CI_ENVIRONMENT_SLUG");
625 2 : char * project_path_slug=cJSON_get_key(env_json, "CI_PROJECT_PATH_SLUG");
626 2 : char * deploy_app_domain=cJSON_get_key(env_json, "DEPLOY_DOMAIN_APP");
627 : char deploy_domain[256];
628 2 : sprintf(deploy_domain, "%s.%s.%s",env_slug,project_path_slug,deploy_app_domain);
629 2 : debug("new domain %s\n",deploy_domain);
630 2 : cJSON_AddItemToObject(env_json, "DEPLOY_DOMAIN", cJSON_CreateString(deploy_domain));
631 : }
632 : }
633 12 : debug("building paths\n");
634 12 : sprintf(baseHREF,"http://%s",cJSON_get_key(env_json, "DEPLOY_DOMAIN"));
635 12 : sprintf((char *)tagHREF,"%s/%s",baseHREF,build_ref_slug);
636 12 : sprintf((char *)basePATH,"%s/deploy/domain/%s",param->prefix,cJSON_get_key(env_json, "DEPLOY_DOMAIN"));
637 12 : sprintf((char *)tagPATH,"%s/public/%s",basePATH,build_ref_slug);
638 : // **** read release and udate with new release
639 12 : sprintf(subPATH,"/%s/files",build_ref_slug);
640 : }
641 : else
642 : {
643 5 : debug("NOT a production deployment\n");
644 5 : deploy_production=0;
645 5 : if (! cJSON_GetObjectItem(env_json, "DEPLOY_DOMAIN_APP"))
646 : {
647 1 : debug("DEPLOY_DOMAIN_APP not found\n");
648 1 : Write_dyn_trace(trace, none,"ERR: Environment not OK, $DEPLOY_APP_DOMAIN not defined\n");
649 1 : exitcode=1;
650 1 : return exitcode;
651 : }
652 4 : if(validate_project_path_slug(env_json, trace,1)!=0)
653 : {
654 1 : debug("ERR: Project_Path_slug, Environment not OK!! \n");
655 1 : Write_dyn_trace(trace, red,"ERR: Environment not OK!! \n");
656 1 : exitcode=1;
657 1 : return exitcode;
658 : }
659 3 : debug("assemble domain\n");
660 3 : char * env_slug=cJSON_get_key(env_json, "CI_ENVIRONMENT_SLUG");
661 3 : char * project_path_slug=cJSON_get_key(env_json, "CI_PROJECT_PATH_SLUG");
662 3 : char * deploy_app_domain=cJSON_get_key(env_json, "DEPLOY_DOMAIN_APP");
663 3 : debug("parts%s.%s.%s\n",env_slug,project_path_slug,deploy_app_domain);
664 :
665 :
666 : // set the variables for directory and HREF
667 3 : sprintf(baseHREF,"http://%s.%s.%s",cJSON_get_key(env_json, "CI_ENVIRONMENT_SLUG"),cJSON_get_key(env_json, "CI_PROJECT_PATH_SLUG"), cJSON_get_key(env_json, "DEPLOY_DOMAIN_APP"));
668 3 : sprintf((char *)basePATH,"%s/deploy/sites/%s/%s",param->prefix,cJSON_get_key(env_json, "CI_PROJECT_PATH_SLUG"),cJSON_get_key(env_json, "CI_ENVIRONMENT_SLUG"));
669 : // non domain deploys have no tags history
670 3 : sprintf((char *)tagPATH,"%s/public",basePATH);
671 3 : sprintf((char *)tagHREF,"%s",baseHREF);
672 3 : sprintf(subPATH,"/files");
673 : char deploy_domain[256];
674 3 : sprintf(deploy_domain, "%s.%s.%s",env_slug,project_path_slug,deploy_app_domain);
675 3 : debug("new domain %s\n",deploy_domain);
676 3 : if (cJSON_get_key(env_json,"DEPLOY_DOMAIN"))
677 2 : cJSON_ReplaceItemInObject(env_json, "DEPLOY_DOMAIN", cJSON_CreateString(deploy_domain));
678 : else
679 1 : cJSON_AddItemToObject(env_json, "DEPLOY_DOMAIN", cJSON_CreateString(deploy_domain));
680 :
681 : }
682 :
683 15 : debug("checking namespace\n");
684 15 : if (check_namespace(opaque, basePATH)!=0)
685 : {
686 2 : Write_dyn_trace(trace, red,"\nERROR: Namespace belongs to another Project!! \n");
687 2 : exitcode=1;
688 2 : return exitcode;
689 : }
690 :
691 13 : _mkdir("/files",tagPATH);
692 :
693 :
694 : // on deploy production we create a http config file
695 : //if (deploy_production)
696 : {
697 13 : exitcode= write_http_config(opaque,0,basePATH,cJSON_get_key(env_json, "DEPLOY_DOMAIN"));
698 13 : if (exitcode){debug("Failed create http config\n");return exitcode;}
699 12 : exitcode= verify_http_config(opaque);
700 12 : if (exitcode)
701 : {
702 1 : debug("Failed nginx -t \n");
703 1 : delete_http_config(opaque,basePATH);
704 :
705 1 : return exitcode;
706 : }
707 11 : else exitcode=reload_http_config(opaque);
708 : }
709 : // check if dns points to this instance for this url
710 11 : if (!exitcode) exitcode= url_check(opaque, basePATH,baseHREF);
711 11 : if (!exitcode)
712 : {
713 8 : exitcode=write_namespace(opaque, basePATH);
714 8 : if (!exitcode) debug("Failed to write_namespace\n");
715 : }
716 11 : _rmdir("/files",tagPATH);
717 11 : if (!exitcode)
718 : {
719 : cJSON * dep_path;
720 8 : cJSON_ArrayForEach(dep_path, cJSON_GetObjectItem(env_json, "DEPLOY_RELEASE_PATH"))
721 : {
722 0 : char * source=dep_path->child->valuestring;
723 0 : char * target=dep_path->child->string;
724 0 : char * dir=NULL;
725 0 : split_path_file_2_path(&dir,target);
726 : char files_path[1024];
727 0 : sprintf(files_path,"%s/files%s",tagPATH,dir);
728 0 : _mkdir(NULL,files_path);
729 0 : debug("s=%s, t=%s,tdir=%s, >%s<\n",source,target,dir,files_path);
730 0 : if (dir) free(dir);
731 : // rsync
732 0 : newarg[0]="/usr/bin/rsync";
733 0 : newarg[1]="-r";
734 0 : newarg[2]=(char *)var_arg1_string;
735 0 : sprintf((char *)newarg[2],"%s%s",cJSON_get_key(env_json, "CI_PROJECT_DIR"),source);
736 0 : newarg[3]=(char *)var_arg2_string;
737 0 : sprintf((char *)newarg[3],"%s%s",files_path,target);
738 0 : newarg[4]=NULL;
739 0 : Write_dyn_trace(trace, none,"+ rsync release ");
740 0 : Write_dyn_trace_pad(trace, cyan,75-16,"%s -> %s",source,target);
741 0 : debug("cmd: %s %s %s %s\n",newarg[0],newarg[1],newarg[2],newarg[3]);
742 0 : exitcode=cmd_exec(opaque);
743 0 : if (!exitcode)
744 0 : Write_dyn_trace(trace, green,"[OK]\n");
745 : else
746 0 : Write_dyn_trace(trace, red,"[FAILED]\n");
747 0 : if (exitcode)
748 0 : {debug("Failed exec rsync %s\n",newarg[2]);return exitcode;}
749 : }
750 : }
751 : } // environment check ok
752 :
753 :
754 : // get gitlab release info
755 12 : cJSON * grelease_tag=NULL;
756 12 : if (!exitcode && cJSON_GetObjectItem(env_json, "CI_COMMIT_TAG"))
757 : {
758 8 : Write_dyn_trace_pad(trace, none,75,"+ get gitlab tag ...");
759 8 : update_details(trace);
760 8 : debug("getting release from gitlab and put into html buffer\n");
761 8 : if (!get_release(opaque, &grelease_tag))
762 : {
763 7 : char * temp_out=cJSON_get_key(grelease_tag, "message");
764 7 : if (temp_out)
765 : {
766 6 : debug("release info ok \n");
767 6 : Write_dyn_trace(trace, green,"[OK]\n");
768 : }
769 : else
770 : {
771 1 : debug ("no release info\n");
772 1 : Write_dyn_trace(trace, bold_magenta,"\nNO release info\n");
773 : }
774 : }
775 : else
776 : {
777 1 : Write_dyn_trace(trace, bold_magenta,"\n API Problem\n");
778 1 : debug ("problem getting tag from gitlab\n");
779 : }
780 8 : update_details(trace);
781 : }
782 : // create this release=> for all environment
783 : char filepath[1024];
784 12 : char * last_tag=NULL;
785 12 : char * release_print=NULL;
786 12 : char * release_json_js_print=NULL;
787 12 : cJSON * releases=NULL;
788 12 : cJSON * this_release=NULL;
789 12 : int clean_tag=0;
790 :
791 12 : if (!exitcode && deploy_production)
792 : {
793 7 : clean_tag=is_clean_tag(opaque,cJSON_get_key(env_json, "CI_COMMIT_TAG"),(const char *[]) {"BETA","TEST","RC","PRC","ALPHA",NULL});
794 : }
795 12 : if (!exitcode && deploy_production && clean_tag)
796 : {
797 5 : last_tag=strdup(cJSON_get_key(env_json, "CI_COMMIT_TAG"));
798 7 : } else if (!exitcode && deploy_production)
799 : {
800 2 : last_tag=check_last_tag(opaque,basePATH);
801 : }
802 :
803 12 : debug("last_tag: %s\n",last_tag);
804 12 : if (!exitcode)
805 : {
806 8 : this_release= create_thisrelease_json( opaque , grelease_tag, deploy_production, basePATH,subPATH);
807 : }
808 12 : if (!exitcode && this_release)
809 : {
810 8 : release_print = create_releases_json( opaque , this_release, &releases, deploy_production);
811 : }
812 12 : if (!exitcode && release_print)
813 : {
814 8 : release_json_js_print= create_release_json_js (opaque , baseHREF, release_print,1 , last_tag); // tagHREF?
815 : }
816 : //
817 : //NOW write it!!! in tagPATH
818 12 : if (!exitcode && release_json_js_print)
819 : {
820 : // **** read release and udate with new release
821 8 : sprintf(filepath,"%s/deployw_json.js",tagPATH);
822 8 : newarg[0]="write_file";
823 8 : newarg[1]=(char *)filepath;
824 8 : newarg[2]=(char *)release_json_js_print;
825 8 : newarg[3]=NULL;
826 8 : debug("deployw_json.js:==>\n%s\n\n",newarg[2]);
827 8 : if (deploy_production)
828 7 : Write_dyn_trace_pad(trace, none,75,"+ write /%s/deployw_json.js",build_ref_slug);
829 : else
830 1 : Write_dyn_trace_pad(trace, none,75,"+ write /%s/deployw_json.js",build_ref_slug);
831 8 : exitcode=cmd_write(opaque);
832 8 : if (!exitcode)
833 8 : Write_dyn_trace(trace, green,"[OK]\n");
834 : else
835 0 : Write_dyn_trace(trace, red,"[FAILED]\n");
836 :
837 8 : if (exitcode)
838 0 : error("\nERR: writing deployw_json.js\n");
839 : else
840 8 : debug ("wrote %s\n", newarg[1]);
841 : }
842 :
843 : // cleanup
844 12 : if (releases) { cJSON_Delete(releases);releases=NULL; }
845 12 : if (release_print) {free(release_print); release_print=NULL; }
846 12 : if (release_json_js_print) {free(release_json_js_print); release_json_js_print=NULL; }
847 12 : if (grelease_tag){cJSON_Delete(grelease_tag); grelease_tag=NULL;}
848 12 : update_details(trace);
849 : // ******************************************************************
850 : // now do the things for production env!, this time save to basePATH
851 : // ******************************************************************
852 12 : if (!exitcode && deploy_production && this_release)
853 : {
854 : // **** read release and udate with new release
855 7 : sprintf(filepath,"%s/public/release.json",basePATH);
856 7 : releases=read_release_json(opaque, filepath);
857 7 : release_print=create_releases_json(opaque, this_release, &releases, 1);
858 7 : newarg[0]="write_file";
859 7 : newarg[1]=(char *)filepath;
860 7 : newarg[2]=(char *)release_print;
861 7 : newarg[3]=NULL;
862 7 : if (newarg[2])
863 : {
864 7 : debug("release.json:==>\n%s\n\n",newarg[2]);
865 7 : Write_dyn_trace_pad(trace, none,75,"+ write /release.json");
866 7 : exitcode=cmd_write(opaque);
867 7 : if (exitcode){
868 0 : Write_dyn_trace(trace, red,"[FAIL]\n");
869 0 : error("\nERR: writing release.json\n");
870 : }
871 : else
872 : {
873 7 : Write_dyn_trace(trace, green,"[OK]\n");
874 7 : debug ("wrote %s\n", newarg[1]);
875 : }
876 : }
877 : else
878 0 : { Write_dyn_trace(trace, red,"\nERR: preparing release.json \n"); error(" getting print JSONBUFF\n");exitcode=1; }
879 : }
880 12 : update_details(trace);
881 12 : if (!exitcode && release_print) release_json_js_print= create_release_json_js(opaque, baseHREF,release_print,0,last_tag);
882 12 : if (release_json_js_print)
883 : { // write it
884 7 : sprintf(filepath,"%s/public/deployw_json.js",basePATH);
885 7 : newarg[0]="write_file";
886 7 : newarg[1]=(char *)filepath;
887 7 : newarg[2]=(char *)release_json_js_print;
888 7 : newarg[3]=NULL;
889 : //debug("release.json:==>\n%s\n\n",newarg[2]);
890 7 : Write_dyn_trace_pad(trace, none,75,"+ write /deployw_json.js");
891 7 : exitcode=cmd_write(opaque);
892 7 : if (exitcode){
893 0 : Write_dyn_trace(trace, red,"[FAIL]\n");
894 0 : error("\nERR: writing deployw_json.js\n");
895 : }
896 : else
897 : {
898 7 : Write_dyn_trace(trace, green,"[OK]\n");
899 7 : debug ("wrote %s\n", newarg[1]);
900 : }
901 :
902 7 : free(release_json_js_print);
903 : }
904 5 : else if (deploy_production)
905 : {
906 2 : Write_dyn_trace(trace, red,"\nERR: preparing deployw_json.js \n");
907 2 : error("\nERR: getting data for deployw_json.js\n");
908 2 : exitcode=1;
909 : }
910 : // And clean it up.
911 12 : if (release_print) free(release_print);
912 12 : if (last_tag) free(last_tag);
913 12 : if(this_release)
914 : {
915 8 : cJSON_Delete(this_release);
916 8 : debug ("cJSON_delete releases OK\n");
917 8 : this_release=NULL;
918 : }
919 12 : if(releases)
920 : {
921 7 : cJSON_Delete(releases);
922 7 : debug ("cJSON_delete releases OK\n");
923 7 : releases=NULL;
924 : }
925 12 : update_details(trace);
926 :
927 : // symlink css/js/fonts/bootstrap etc for baseHREF
928 : // TODO should check if no .LAYOUT before symlinking
929 12 : if (!exitcode )
930 : {
931 8 : newarg[0]="/bin/sh";
932 8 : newarg[1]="-c";
933 8 : newarg[2]=(char *)var_arg1_string;
934 8 : sprintf((char *)newarg[2],"/bin/ln -sf %s/deploy/config/html_deploy/* %s/public/",param->prefix,basePATH );
935 8 : newarg[3]=NULL;
936 8 : Write_dyn_trace_pad(trace, none,75,"+ symlink webapp to /");
937 8 : debug("cmd: %s %s %s \n",newarg[0],newarg[1],newarg[2]);
938 8 : exitcode=cmd_exec(opaque);
939 8 : if (exitcode){
940 0 : Write_dyn_trace(trace, red,"[FAIL]\n");
941 0 : debug("Failed create webapp symlink %s",newarg[2]);
942 : }
943 : else
944 : {
945 8 : Write_dyn_trace(trace, green,"[OK]\n");
946 : }
947 8 : update_details(trace);
948 : }
949 : // symlink index.html for the tag release
950 12 : if (!exitcode && deploy_production)
951 : {
952 7 : newarg[0]="/bin/sh";
953 7 : newarg[1]="-c";
954 7 : newarg[2]=(char *)var_arg1_string;
955 7 : sprintf((char *)newarg[2],"/bin/ln -sf %s/deploy/config/html_deploy/index.html %s/",param->prefix,tagPATH );
956 7 : newarg[3]=NULL;
957 7 : Write_dyn_trace_pad(trace, none,75,"+ symlink index.html to /%s",build_ref_slug);
958 7 : debug("cmd: %s %s %s \n",newarg[0],newarg[1],newarg[2]);
959 7 : exitcode=cmd_exec(opaque);
960 7 : if (exitcode){
961 0 : Write_dyn_trace(trace, red,"[FAIL]\n");
962 0 : debug("Failed create symlink %s\n",newarg[2]);
963 : }
964 : else
965 : {
966 7 : Write_dyn_trace(trace, green,"[OK]\n");
967 : }
968 7 : update_details(trace);
969 : }
970 : // create release badge on a clean_tag ( no beta or RC or test ...)
971 12 : if (!exitcode && deploy_production && clean_tag)
972 : {
973 5 : debug("\n create badge\n");
974 : // Create the svg badge release on top level
975 5 : char * svg_out=NULL;
976 5 : if (cJSON_GetObjectItem(env_json, "CI_COMMIT_TAG"))
977 : {
978 5 : make_svg_badge("Release", cJSON_get_key(env_json, "CI_COMMIT_TAG"),&svg_out);
979 : /* NO deploy release without TAG
980 : else
981 : {
982 : char commit_short[10];
983 : sprintf(commit_short,"%.*s",8,cJSON_get_key(env_json, "CI_COMMIT_SHA"));
984 : make_svg_badge("Commit", commit_short,&svg_out);
985 : } */
986 :
987 : }
988 5 : if (svg_out)
989 : {
990 5 : newarg[0]="write_file";
991 5 : newarg[1]=(char *)var_arg1_string;
992 5 : sprintf((char *)newarg[1],"%s/public/tag.svg",basePATH);
993 5 : newarg[2]=svg_out;
994 5 : newarg[3]=NULL;
995 5 : Write_dyn_trace_pad(trace, none,75,"+ write public/tag.svg");
996 :
997 5 : exitcode=cmd_write(opaque);
998 5 : if (!exitcode) { debug("wrote %s, %d bytes\n",newarg[1],strlen(svg_out));}
999 5 : if (exitcode){
1000 0 : Write_dyn_trace(trace, red,"[FAIL]\n");
1001 : }
1002 : else
1003 : {
1004 5 : Write_dyn_trace(trace, green,"[OK]\n");
1005 : }
1006 5 : free(svg_out);
1007 5 : svg_out=NULL;
1008 : }
1009 : else
1010 0 : {Write_dyn_trace(trace, red,"\n- Failed creating svg release tag\n"); debug("Failed making svg release tag\n"); }
1011 5 : update_details(trace);
1012 : }
1013 : // symlink latest to this release, only on clean tag
1014 12 : if (!exitcode && deploy_production && clean_tag )
1015 : {
1016 : // ln -sf tag latest
1017 5 : newarg[0]="/bin/ln";
1018 5 : newarg[1]="-sf";
1019 5 : newarg[2]=(char *)var_arg1_string;
1020 5 : sprintf((char *)newarg[2],"%s",tagPATH);
1021 5 : newarg[3]=(char *)var_arg2_string;
1022 5 : sprintf((char *)newarg[3],"%s/public/latest",basePATH);
1023 5 : newarg[4]=NULL;
1024 5 : Write_dyn_trace_pad(trace, none,75,"+ symlink latest");
1025 :
1026 5 : int thiserror=0;
1027 : // unlink, only throw error on none existing file
1028 5 : if (unlink (newarg[3])!=0 && (thiserror=errno)!=ENOENT) sock_error_no("unlink sysmlink latest",thiserror);
1029 5 : exitcode=cmd_exec(opaque);
1030 5 : if (exitcode){
1031 0 : Write_dyn_trace(trace, red,"[FAIL]\n");
1032 0 : debug("Failed ln -sf %s %s\n",newarg[2],newarg[3]);
1033 0 : return exitcode;
1034 : }
1035 5 : else {debug("ln -sf %s %s\n",newarg[2],newarg[3]);Write_dyn_trace(trace, green,"[OK]\n");}
1036 : }
1037 : // write public/latest.tag, contains latest tag info
1038 12 : if (!exitcode && deploy_production && clean_tag )
1039 : {
1040 5 : char * tag=cJSON_get_key(env_json, "CI_COMMIT_TAG");
1041 5 : newarg[0]="write_file";
1042 5 : newarg[1]=(char *)var_arg1_string;
1043 5 : sprintf((char *)newarg[1],"%s/public/latest.tag",basePATH);
1044 5 : newarg[2]= tag;
1045 5 : newarg[3]=NULL;
1046 5 : Write_dyn_trace_pad(trace, none,75,"+ write public/latest.tag");
1047 :
1048 5 : exitcode=cmd_write(opaque);
1049 5 : if (!exitcode)
1050 5 : Write_dyn_trace(trace, green,"[OK]\n");
1051 : else
1052 0 : Write_dyn_trace(trace, red,"[FAILED]\n");
1053 :
1054 5 : if (!exitcode) { debug("wrote %s => %s\n",newarg[1],newarg[2]);}
1055 : }
1056 12 : update_details(trace);
1057 12 : if (!exitcode && deploy_production && validate_key(env_json, "DEPLOY_CONFIG_HTTPS","True" )==0)
1058 : {
1059 : //config https
1060 :
1061 0 : debug("start letsencript\n");
1062 : // check if letsencript config exists, if not create new cert
1063 0 : exitcode=letsencrypt(opaque,cJSON_get_key(env_json, "DEPLOY_DOMAIN"),cJSON_get_key(env_json, "GITLAB_USER_EMAIL"));
1064 : // write https
1065 0 : if (!exitcode)
1066 : {
1067 0 : exitcode= write_http_config(opaque,1,basePATH,cJSON_get_key(env_json, "DEPLOY_DOMAIN"));
1068 0 : if (exitcode){debug("Failed create http config\n");return exitcode;}
1069 0 : exitcode= verify_http_config(opaque);
1070 0 : if (exitcode)
1071 : {
1072 0 : debug("Failed nginx -t \n");
1073 0 : delete_http_config(opaque,basePATH);
1074 :
1075 0 : return exitcode;
1076 : }
1077 0 : else exitcode=reload_http_config(opaque);
1078 : }
1079 0 : else debug("ERR: let's encrypt failed\n");
1080 0 : update_details(trace);
1081 :
1082 : }
1083 12 : update_details(trace);
1084 12 : return exitcode;
1085 : }
1086 :
1087 :
1088 : /*
1089 : ---
1090 : projects:
1091 : - projecturl1
1092 : - projecturlb
1093 :
1094 : repos:
1095 : - rpm:
1096 : - el7:
1097 : - x86_64
1098 : - i386
1099 : - apt:
1100 : - test2: apt-test2
1101 :
1102 : */
1103 :
1104 : /*------------------------------------------------------------------------
1105 : * Internal Command : rpm_init : filter the env, init rpm
1106 : *------------------------------------------------------------------------*/
1107 0 : int cmd_repo_config(void * opaque)
1108 : {
1109 : // feedback buffer
1110 0 : int exitcode=0;
1111 0 : struct trace_Struct *trace=((data_exchange_t *)opaque)->trace;
1112 :
1113 : // env json
1114 0 : cJSON * env_json=((data_exchange_t *)opaque)->env_json;
1115 : char * newarg[8];
1116 : // no need to set environment for individual commands
1117 0 : ((data_exchange_t *)opaque)->needenvp=0;
1118 0 : ((data_exchange_t *)opaque)->paramlist=(char **)newarg;
1119 0 : parameter_t * param=((data_exchange_t *)opaque)->parameters;
1120 : char var_arg1_string[1024];
1121 : char var_arg2_string[1024];
1122 : // char * var_dest_dir_string[1024];
1123 0 : int deploy_production=0;
1124 0 : debug("checking environment\n");
1125 : char basePATH[1024];
1126 : char baseHREF[1024];
1127 : char baseHREF_prod[1024];
1128 :
1129 : char repoNAME[1024];
1130 0 : int cnt=0;
1131 :
1132 0 : if ((cnt=check_presence(env_json,
1133 : (char *[])
1134 0 : {"CI_PROJECT_PATH_SLUG","CI_ENVIRONMENT_SLUG","CI_ENVIRONMENT_NAME","CI_PROJECT_PATH","CI_PROJECT_NAME","CI_PROJECT_DIR","CI_COMMIT_SHA","CI_COMMIT_REF_SLUG","CI_PROJECT_URL","CI_JOB_TOKEN","CI_PROJECT_ID",NULL}
1135 : , trace)))
1136 : {
1137 0 : Write_dyn_trace(trace, none,"ERROR: %d Environment variable(s) Missing\n",cnt);
1138 0 : debug("\nERROR: %d Environment variable(s) Missing!!!\n",cnt);
1139 0 : exitcode=1;
1140 : }
1141 : else
1142 : {
1143 : // inform deployctl of environment deployment
1144 0 : debug("Deploy environment :%s\n",cJSON_get_key(env_json, "CI_ENVIRONMENT_NAME"));
1145 : //Write_dyn_trace(trace, none,"Deploy environment :%s\n",cJSON_GetObjectItem(env_json, "CI_ENVIRONMENT_NAME")->valuestring);
1146 0 : if (validate_key(env_json, "CI_ENVIRONMENT_NAME", "production")==0)
1147 : {
1148 0 : debug("RPM _config\n");
1149 0 : deploy_production=1;
1150 0 : if (! cJSON_GetObjectItem(env_json, "DEPLOY_DOMAIN"))
1151 : { // we got no deploydomain, so make one
1152 : // as per : $CI_ENVIRONMENT_SLUG.$CI_PROJECT_PATH_SLUG.$DEPLOY_DOMAIN_APP
1153 :
1154 0 : debug("\nNo Deploy demain:\n");
1155 0 : if(validate_project_path_slug(env_json, trace, 1)!=0)
1156 : {
1157 0 : debug("no valid project path\n");
1158 0 : Write_dyn_trace(trace, none,"Environment not OK!! \n ** \"DEPLOY_DOMAIN\" and/or \"DEPLOY_APP_DOMAIN\" not defined ** \n");
1159 0 : exitcode=1;
1160 0 : return exitcode;
1161 : }
1162 : else
1163 : {
1164 0 : debug("extracting new domain\n");
1165 0 : char * env_slug=cJSON_get_key(env_json, "CI_ENVIRONMENT_SLUG");
1166 0 : char * project_path_slug=cJSON_get_key(env_json, "CI_PROJECT_PATH_SLUG");
1167 0 : char * deploy_app_domain=cJSON_get_key(env_json, "DEPLOY_DOMAIN_APP");
1168 : char deploy_domain[256];
1169 0 : sprintf(deploy_domain, "%s.%s.%s",env_slug,project_path_slug,deploy_app_domain);
1170 0 : debug("new domain %s\n",deploy_domain);
1171 0 : cJSON_AddItemToObject(env_json, "DEPLOY_DOMAIN", cJSON_CreateString(deploy_domain));
1172 : }
1173 : }
1174 0 : debug("building paths\n");
1175 0 : sprintf(baseHREF,"http://%s",cJSON_get_key(env_json, "DEPLOY_DOMAIN"));
1176 :
1177 0 : if (deploy_production && validate_key(env_json, "DEPLOY_CONFIG_HTTPS","True" )==0)
1178 0 : sprintf(baseHREF_prod,"https://%s",cJSON_get_key(env_json, "DEPLOY_DOMAIN"));
1179 : else
1180 0 : sprintf(baseHREF_prod,"http://%s",cJSON_get_key(env_json, "DEPLOY_DOMAIN"));
1181 :
1182 :
1183 0 : sprintf((char *)basePATH,"%s/deploy/domain/%s",param->prefix,cJSON_get_key(env_json, "DEPLOY_DOMAIN"));
1184 0 : char * tmp=cJSON_get_key(env_json, "DEPLOY_REPO_NAME");
1185 0 : if (tmp && strlen(tmp)>0) sprintf(repoNAME,"%s",tmp); else sprintf(repoNAME,"%s",cJSON_get_key(env_json, "CI_PROJECT_NAME"));
1186 :
1187 : }
1188 : else
1189 : {
1190 :
1191 0 : Write_dyn_trace(trace, none,"ERROR: NOT a production deployment\n");
1192 0 : debug("\nERROR: NOT a production deployment\n");
1193 0 : exitcode=1;
1194 0 : return exitcode;
1195 : }
1196 :
1197 0 : debug("checking namespace\n");
1198 0 : if (check_namespace(opaque, basePATH)!=0)
1199 : {
1200 0 : Write_dyn_trace(trace, none,"ERR: Namespace belongs to another Project!! \n");
1201 0 : exitcode=1;
1202 0 : return exitcode;
1203 : }
1204 0 : debug("make the directory structure for rpm\n");
1205 :
1206 : //make the directory structure for rpm
1207 0 : newarg[0]="/bin/mkdir";
1208 0 : newarg[1]="-p";
1209 0 : newarg[2]=(char *)var_arg1_string;
1210 0 : sprintf((char *)newarg[2],"%s/public",basePATH);
1211 0 : newarg[3]=NULL;
1212 0 : Write_dyn_trace_pad(trace, none,75,"+ mkdir repo");
1213 :
1214 0 : debug("cmd: %s %s %s \n",newarg[0],newarg[1],newarg[2]);
1215 0 : exitcode=cmd_exec(opaque);
1216 :
1217 0 : if (exitcode)
1218 0 : Write_dyn_trace(trace, red,"[FAILED]\n");
1219 : else
1220 0 : Write_dyn_trace(trace, green,"[OK]\n");
1221 :
1222 0 : if (exitcode) {debug("Failed exec mkdir %s\n",newarg[2]);return exitcode;}
1223 :
1224 0 : exitcode= write_http_config(opaque,2,basePATH,cJSON_get_key(env_json, "DEPLOY_DOMAIN"));
1225 0 : if (exitcode){debug("Failed create http config\n");return exitcode;}
1226 0 : exitcode= verify_http_config(opaque);
1227 0 : if (exitcode)
1228 : {
1229 0 : debug("Failed nginx -t \n");
1230 0 : delete_http_config(opaque,basePATH);
1231 :
1232 0 : return exitcode;
1233 : }
1234 0 : else exitcode=reload_http_config(opaque);
1235 :
1236 : // check if dns points to this instance for this url
1237 0 : if (!exitcode) exitcode= url_check(opaque, basePATH,baseHREF);
1238 0 : if (!exitcode)
1239 : {
1240 0 : exitcode=write_namespace(opaque, basePATH);
1241 0 : if (!exitcode) debug("Failed to write_namespace\n");
1242 : }
1243 : // read yalm_file
1244 0 : char * repo_file=NULL;
1245 0 : cJSON * repo_json=NULL;
1246 0 : repo_file =read_file(cJSON_get_key(env_json, "CI_PROJECT_DIR"), "repo.yaml");
1247 0 : if (!repo_file)
1248 : {
1249 0 : debug("Failed to get repofile \n");
1250 0 : exitcode=1;
1251 0 : return exitcode;
1252 : }
1253 0 : else debug("read repo.yaml ok\n");
1254 : // convert to json
1255 0 : repo_json= yaml_sting_2_cJSON (opaque ,repo_file);
1256 : // validate json
1257 0 : if (!repo_json)
1258 : {
1259 0 : debug("Failed to create cJSON from yaml \n");
1260 0 : free(repo_file);
1261 0 : exitcode=1;
1262 0 : return exitcode;
1263 : }
1264 : else
1265 : {
1266 0 : debug(" got repo_json\n");
1267 : }
1268 : // returns an array of documents
1269 : // we only want first one
1270 0 : cJSON * temp=repo_json;
1271 0 : repo_json=cJSON_DetachItemFromArray(temp, 0);
1272 0 : cJSON_Delete(temp);
1273 :
1274 : // we need a minimun of projects and repos
1275 0 : if (check_presence(repo_json,(char *[]){"projects","repos",NULL}, trace)!=0)
1276 : {
1277 0 : Write_dyn_trace(trace, red,"ERROR: missing yaml entries\n");
1278 0 : debug("\nERROR: missing yaml entries\n");
1279 0 : if (repo_json) cJSON_Delete(repo_json);
1280 : exitcode=1;
1281 : return exitcode;
1282 : } else
1283 : {
1284 0 : debug("got correct yaml entries\n");
1285 : }
1286 : //create directory structure for rpm
1287 0 : cJSON * endpoints=NULL;
1288 0 : if (!exitcode )
1289 : {
1290 0 : endpoints = create_repo_dirs(opaque, basePATH , cJSON_GetObjectItem(repo_json, "repos"));
1291 : }
1292 : else
1293 : {
1294 0 : Write_dyn_trace(trace, none,"ERR: creating Repodirs\n");
1295 :
1296 0 : debug("ERR: creating Repodirs\n");
1297 : }
1298 0 : update_details(trace);
1299 : // read description.md, convert to html and add to repo.json
1300 0 : if (!exitcode && repo_json)
1301 : {
1302 0 : char * tmp = read_file(cJSON_get_key(env_json, "CI_PROJECT_DIR"), "description.md");
1303 0 : if (tmp)
1304 : {
1305 0 : char * tmp_html=NULL;
1306 0 : char * sub_md=substitute_repo_script(tmp,repoNAME, baseHREF_prod, 0,0);
1307 0 : if (sub_md)
1308 : {
1309 0 : tmp_html=html_body_release(sub_md);
1310 0 : free(sub_md);
1311 : }
1312 : else
1313 : {
1314 0 : tmp_html=html_body_release(tmp);
1315 : }
1316 0 : free(tmp);
1317 0 : if (tmp_html)
1318 : {
1319 0 : cJSON_AddItemToObject(repo_json, "description",cJSON_CreateString(tmp_html));
1320 0 : free(tmp_html);
1321 : }
1322 : }
1323 : }
1324 :
1325 : //
1326 0 : if (!exitcode && repo_json )
1327 : {
1328 : // **** write repo.json and deployw_json.js
1329 0 : cJSON_AddItemToObject(repo_json, "endpoints",endpoints);
1330 0 : cJSON_AddItemToObject(repo_json, "base_path", cJSON_CreateString(basePATH));
1331 0 : cJSON_AddItemToObject(repo_json, "base_href", cJSON_CreateString(baseHREF_prod));
1332 0 : add_deploy_info_json(opaque,repo_json);
1333 : char filepath[1024];
1334 0 : char * repo_print=cJSON_Print(repo_json);
1335 0 : if (repo_print)
1336 : { // write it out
1337 0 : sprintf(filepath,"%s/public/repo.json",basePATH);
1338 0 : newarg[0]="write_file";
1339 0 : newarg[1]=(char *)filepath;
1340 0 : newarg[2]=repo_print;
1341 0 : newarg[3]=NULL;
1342 0 : debug("repo.json:==>\n%s\n\n",newarg[2]);
1343 0 : Write_dyn_trace_pad(trace, none,75,"+ write /repo.json");
1344 :
1345 0 : exitcode=cmd_write(opaque);
1346 0 : if (exitcode)
1347 0 : Write_dyn_trace(trace, red,"[FAILED]\n");
1348 : else
1349 0 : Write_dyn_trace(trace, green,"[OK]\n");
1350 : }
1351 0 : char * deployw_prt=NULL;
1352 0 : if (!exitcode && repo_print)
1353 : {
1354 : // convert to js variables
1355 0 : deployw_prt=create_repo_json_js (opaque, baseHREF_prod, repo_print);
1356 : }
1357 0 : if (!exitcode && deployw_prt)
1358 : { // wrtie deployw_json.js
1359 0 : sprintf(filepath,"%s/public/deployw_json.js",basePATH);
1360 0 : newarg[0]="write_file";
1361 0 : newarg[1]=(char *)filepath;
1362 0 : newarg[2]=deployw_prt;
1363 0 : newarg[3]=NULL;
1364 0 : debug("deployw_json_js:==>\n%s\n\n",newarg[2]);
1365 0 : Write_dyn_trace_pad(trace, none,75,"+ write /deployw_json_js");
1366 0 : exitcode=cmd_write(opaque);
1367 : }
1368 0 : if (deployw_prt) free(deployw_prt);
1369 0 : if (repo_print) free(repo_print);
1370 :
1371 0 : if (exitcode)
1372 : {
1373 0 : error("\nERR: writing json data\n");
1374 0 : Write_dyn_trace(trace, red,"[FAILED]\n");
1375 : }
1376 0 : else Write_dyn_trace(trace, green,"[OK]\n");
1377 : }
1378 0 : update_details(trace);
1379 0 : if ( endpoints && !exitcode) exitcode=init_repo_dirs(opaque, basePATH, endpoints);
1380 :
1381 : //if (endpoints) cJSON_Delete(endpoints);
1382 :
1383 :
1384 : // symlink css/js/fonts/bootstrap etc for baseHREF
1385 : // TODO should check if no .LAYOUT before symlinking
1386 0 : if (!exitcode )
1387 : {
1388 0 : newarg[0]="/bin/sh";
1389 0 : newarg[1]="-c";
1390 0 : newarg[2]=(char *)var_arg1_string;
1391 0 : sprintf((char *)newarg[2],"/bin/ln -sf %s/deploy/config/html_deploy/* %s/public/",param->prefix,basePATH );
1392 0 : newarg[3]=NULL;
1393 0 : Write_dyn_trace_pad(trace, none,75,"+ symlink webapp to /");
1394 0 : debug("cmd: %s %s %s \n",newarg[0],newarg[1],newarg[2]);
1395 0 : exitcode=cmd_exec(opaque);
1396 0 : if (exitcode)
1397 : {
1398 0 : Write_dyn_trace(trace, red,"[FAILED]\n");
1399 0 : debug("Failed create symlink %s",newarg[2]);
1400 : }
1401 0 : else Write_dyn_trace(trace, green,"[OK]\n");
1402 :
1403 : }
1404 0 : if (!exitcode )
1405 : {
1406 0 : sprintf((char *)var_arg1_string,"%s/deploy/config/repo_conf/repo.rpm.sh",param->prefix );
1407 0 : sprintf((char *)var_arg2_string,"%s/public/repo.rpm.sh",basePATH );
1408 0 : Write_dyn_trace_pad(trace, none,75,"+ setup repo script rpm ... ");
1409 :
1410 0 : exitcode=copy_script_sh(opaque, var_arg1_string, var_arg2_string, repoNAME, baseHREF, 0,0);
1411 : }
1412 0 : if (!exitcode )
1413 : {
1414 :
1415 0 : sprintf((char *)var_arg1_string,"%s/deploy/config/repo_conf/repo.deb.sh",param->prefix );
1416 0 : sprintf((char *)var_arg2_string,"%s/public/repo.deb.sh",basePATH );
1417 0 : Write_dyn_trace_pad(trace, none,75,"+ setup repo script deb ... ");
1418 :
1419 0 : exitcode=copy_script_sh(opaque, var_arg1_string, var_arg2_string, repoNAME, baseHREF_prod, 0,0);
1420 : }
1421 :
1422 0 : if (repo_json) cJSON_Delete(repo_json);
1423 0 : update_details(trace);
1424 :
1425 0 : if (!exitcode && deploy_production && validate_key(env_json, "DEPLOY_CONFIG_HTTPS","True" )==0)
1426 : {
1427 : //config https
1428 :
1429 0 : debug("start letsencript\n");
1430 : // check if letsencript config exists, if not create new cert
1431 0 : exitcode=letsencrypt(opaque,cJSON_get_key(env_json, "DEPLOY_DOMAIN"),cJSON_get_key(env_json, "GITLAB_USER_EMAIL"));
1432 : // write https
1433 0 : if (!exitcode)
1434 : {
1435 0 : exitcode= write_http_config(opaque,3,basePATH,cJSON_get_key(env_json, "DEPLOY_DOMAIN"));
1436 0 : if (exitcode){debug("Failed create http config\n");return exitcode;}
1437 0 : exitcode= verify_http_config(opaque);
1438 0 : if (exitcode)
1439 : {
1440 0 : debug("Failed nginx -t \n");
1441 0 : delete_http_config(opaque,basePATH);
1442 :
1443 0 : return exitcode;
1444 : }
1445 0 : else exitcode=reload_http_config(opaque);
1446 : }
1447 0 : else debug("ERR: let's encrypt failed\n");
1448 :
1449 : }
1450 : }
1451 0 : return exitcode;
1452 : }
1453 :
1454 : /*------------------------------------------------------------------------
1455 : * Internal Command : rpm_repo_add : add packages to the repo (rmp/deb)
1456 : *------------------------------------------------------------------------*/
1457 0 : int cmd_repo_add(void * opaque)
1458 : {
1459 : // feedback buffer
1460 0 : int exitcode=0;
1461 0 : struct trace_Struct *trace=((data_exchange_t *)opaque)->trace;
1462 : // env json
1463 0 : cJSON * env_json=((data_exchange_t *)opaque)->env_json;
1464 : char * newarg[8];
1465 :
1466 0 : ((data_exchange_t *)opaque)->needenvp=0;
1467 0 : ((data_exchange_t *)opaque)->paramlist=(char **)newarg;
1468 :
1469 0 : debug("checking environment\n");
1470 : char * basePATH;
1471 : char * baseHREF;
1472 0 : int cnt=0;
1473 :
1474 : // do we have minimun environment var's ?
1475 0 : if ((cnt=check_presence(env_json,
1476 0 : (char *[]){"CI_PROJECT_DIR","CI_PROJECT_URL","DEPLOY_REPO_URL",NULL}
1477 : , trace)))
1478 : {
1479 0 : Write_dyn_trace(trace, red,"ERROR: %d Environment variable(s) Missing\n",cnt);
1480 0 : debug("\nERROR: %d Environment variable(s) Missing!!!\n",cnt);
1481 0 : exitcode=1;
1482 0 : return exitcode;
1483 : }
1484 :
1485 0 : baseHREF=cJSON_get_key(env_json, "DEPLOY_REPO_URL");
1486 :
1487 : // get the repository config file
1488 :
1489 0 : cJSON * repos=NULL;
1490 0 : debug(" url repo\n");
1491 0 : Write_dyn_trace_pad(trace, none,75,"+ Getting repo config...");
1492 0 : exitcode=url_repo_base_path (&basePATH,baseHREF,trace);
1493 0 : if (!exitcode)
1494 : {
1495 0 : Write_dyn_trace_pad(trace, none,75,"+ Reading repo config...");
1496 0 : repos=read_json(opaque, basePATH,"/public","repo.json");
1497 :
1498 0 : if (!repos)
1499 : {
1500 0 : Write_dyn_trace(trace, red,"[FAILED]\n ERROR: could not read repo config\n");
1501 0 : debug("\nERROR: could not read repo config\n");
1502 0 : exitcode=1;
1503 : }
1504 0 : else Write_dyn_trace(trace, green,"[OK]\n");
1505 : }
1506 : else
1507 : {
1508 0 : Write_dyn_trace(trace, red,"[FAILED]\n ERROR: could not accuire url base_path_url\n");
1509 0 : debug("\nERROR: could get config request\n");
1510 0 : exitcode=1;
1511 : }
1512 :
1513 : // verify the repo configuration
1514 0 : if (!exitcode)
1515 : {
1516 0 : debug("checking validity of repo config\n");
1517 0 : Write_dyn_trace_pad(trace, none,75,"+ Verify config...");
1518 0 : if ((cnt=check_presence(repos,
1519 : (char *[])
1520 0 : {"projects","endpoints","base_path","base_href","repos",NULL}
1521 : , trace)))
1522 : {
1523 0 : Write_dyn_trace(trace, red,"ERROR: incomplete repo file in repository\n");
1524 0 : debug("\nERROR: incomplete repo file in repository\n");
1525 0 : exitcode=1;
1526 : }
1527 0 : else Write_dyn_trace(trace, green,"[OK]\n");
1528 : }
1529 :
1530 : // check if this project has access to this repository
1531 0 : if (!exitcode)
1532 : {
1533 0 : debug("checking repo_access\n");
1534 0 : Write_dyn_trace_pad(trace, none,75,"+ Checking access...");
1535 0 : if (in_string_array(cJSON_GetObjectItem(repos, "projects"),cJSON_get_key(env_json, "CI_PROJECT_URL"))!=0)
1536 : {
1537 0 : Write_dyn_trace(trace, red,"\nERROR: access denied to this repo\n");
1538 0 : debug("\nERROR: access denied\n");
1539 0 : exitcode=1;
1540 : }
1541 0 : else Write_dyn_trace(trace, green,"[OK]\n");
1542 : }
1543 :
1544 :
1545 : // check if enviroment condition met!
1546 0 : debug("checking environment\n");
1547 0 : char * env_env=cJSON_get_key(env_json, "CI_ENVIRONMENT_NAME");
1548 0 : if ( cJSON_GetObjectItem(repos, "environments"))
1549 : {
1550 0 : debug("environment list defined\n");
1551 : //loop allowed environment list
1552 0 : cJSON * pos=NULL;
1553 0 : int found=0;
1554 0 : cJSON_ArrayForEach(pos,cJSON_GetObjectItem(repos, "environments"))
1555 : {
1556 0 : char * test_item=pos->valuestring;
1557 0 : debug("environment list item: %s\n",test_item);
1558 0 : if (test_item && strcmp(test_item,"none")==0) {found=1; break;}
1559 0 : if (test_item && env_env && strcmp(test_item,"all")==0) {found=1; break;}
1560 0 : if (test_item && env_env && strcmp(test_item,"review/*")==0 && strncmp(env_env,"review/*",8)==0) {found=1; break;}
1561 0 : if (test_item && env_env && strcmp(test_item,env_env)==0) {found=1; break;}
1562 : }
1563 0 : if (!found)
1564 : {
1565 0 : Write_dyn_trace(trace, red,"\n ERROR: defined environment condition not met!\n");
1566 0 : debug("\nERROR: defined environment condition not met!\n");
1567 0 : if (repos) cJSON_Delete(repos);
1568 : exitcode=1;
1569 : return exitcode;
1570 : }
1571 : }
1572 : else
1573 : {
1574 0 : debug("no environment list defined\n");
1575 : // no environment condition defined in repo.yaml, need to have production env
1576 0 : if ( !env_env || strcmp(env_env,"production")!=0 )
1577 : {
1578 0 : Write_dyn_trace(trace, red,"ERROR: default 'production' environment not met!\n");
1579 0 : debug("\nERROR: default 'production' environment not met!\n");
1580 0 : if (repos) cJSON_Delete(repos);
1581 : exitcode=1;
1582 : return exitcode;
1583 : }
1584 : }
1585 0 : debug("start deployment\n");
1586 :
1587 : // inform deployctl of environment deployment, if any
1588 0 : if (env_env)
1589 : {
1590 0 : Write_dyn_trace(trace, yellow," Deployment repo url:");
1591 0 : Write_dyn_trace(trace, cyan," %s\n",baseHREF);
1592 : }
1593 :
1594 : // Start
1595 0 : if (!exitcode)
1596 : {
1597 : // first read repository directories (rpm/deb) and get info on type,distribution and Arch/release (rpm/debian)
1598 0 : cJSON * repo_list=NULL;
1599 : char repo_path_full[1024];
1600 0 : char * user_path=cJSON_GetArrayItem(cJSON_GetObjectItem(env_json, "DEPLOY_REPO_PATH"),0)->valuestring;
1601 0 : sprintf(repo_path_full, "%s%s",cJSON_get_key(env_json, "CI_PROJECT_DIR"),user_path);
1602 :
1603 0 : get_repo_list(opaque,repo_path_full, &repo_list);
1604 :
1605 0 : cJSON * matches=NULL;
1606 0 : cJSON * skips=NULL;
1607 0 : cJSON * symlinks=NULL;
1608 :
1609 : // with the info, create matches and/or symlinks and/or skips
1610 0 : if (repo_list)
1611 : {
1612 0 : match_end_points( opaque, repo_list,cJSON_GetObjectItem(repos, "endpoints"), &matches,&skips,&symlinks);
1613 0 : cJSON_Delete(repo_list);
1614 0 : repo_list=NULL;
1615 : }
1616 0 : update_details(trace);
1617 0 : if (matches && cJSON_GetArraySize(matches)>0)
1618 : {
1619 : // copy the matches in place
1620 0 : Write_dyn_trace(trace, yellow,"\n Copy packages in place from: ");
1621 0 : Write_dyn_trace(trace, cyan,"%s/*\n",user_path);
1622 0 : repo_copy_matches(opaque,matches,basePATH);
1623 0 : update_details(trace);
1624 : }
1625 : // create symlinks for the wildcards
1626 0 : if (symlinks && cJSON_GetArraySize(symlinks)>0)
1627 : {
1628 0 : Write_dyn_trace(trace, yellow,"\n symlink wildcards in place...\n");
1629 0 : repo_create_symlinks(opaque,symlinks,basePATH);
1630 0 : update_details(trace);
1631 : }
1632 : // Inform User of problems
1633 0 : if (skips && cJSON_GetArraySize(skips)>0)
1634 : {
1635 0 : repo_print_skips(opaque,skips);
1636 0 : update_details(trace);
1637 : }
1638 : // update repos if something to update
1639 0 : if (matches)
1640 : {
1641 0 : Write_dyn_trace(trace, yellow,"\n Update repositories...\n");
1642 0 : update_repo_dirs(opaque, basePATH, cJSON_GetObjectItem(repos, "endpoints"));
1643 : }
1644 0 : update_details(trace);
1645 : // cleanup
1646 0 : if (repos) cJSON_Delete(repos);
1647 0 : if (matches) cJSON_Delete(matches);
1648 0 : if (symlinks) cJSON_Delete(symlinks);
1649 0 : if (skips) cJSON_Delete(skips);
1650 : }
1651 :
1652 0 : return exitcode;
1653 : }
|