diff --git a/app/Config/Routes.php b/app/Config/Routes.php index d2a077fd..4e8cab49 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -12,6 +12,8 @@ $routes->get('/chatbottest', 'ChatbotControllerNew::chatbotest'); $routes->get('/chatbot', 'ChatbotControllerNew::chatbot'); $routes->get('/swagger', 'SwaggerController::index', ['filter' => 'authMVC']); +$routes->get('/fedeploy', 'DeployController::fedeploy_view', ['filter' => 'authMVC']); +$routes->post('/fedeploy', 'DeployController::fedeploy', ['filter' => 'authMVC']); // Reminder Mail Notification diff --git a/app/Controllers/DeployController.php b/app/Controllers/DeployController.php new file mode 100644 index 00000000..de73092a --- /dev/null +++ b/app/Controllers/DeployController.php @@ -0,0 +1,286 @@ +myLogger = \Config\Services::mylogger(); + } + // public function fedeploy() + // { + // $request = $this->request; + + // // Multiple zip files: + // // $zipFiles = $this->request->getFileMultiple('zip_files'); + // $zipFiles = $this->request->getFile('zip_files');//('zip_files'); + // // print_r($zipFiles);die(); + + // // Matching dropdown/text values (arrays, indexed same as zip_files[]) + // $zipFolders = (array) $request->getPost('zip_folder'); // e.g. ["web/", "dist/"] + // $s3Buckets = (array) $request->getPost('s3_bucket'); // e.g. ["benefits-app-bucket", ...] + // $s3Prefixes = (array) $request->getPost('s3_prefix'); // e.g. ["hr/", "payroll/"] + // $cfDistributions = (array) $request->getPost('cf_distribution_id'); // e.g. ["DIST1", "DIST1", "DIST2"] + // $cfPathsList = (array) $request->getPost('cf_paths'); // e.g. ["/hr/*", "/hr/special/*", "/payroll/*"] + + // // Path to Python interpreter and deploy_assets.py script + // $pythonBin = getenv('PY_PATH'); // adjust if needed + // $scriptPath = getenv('PY_SCRIPT_PATH'); // full path to your script + + // $results = []; + + // if (empty($zipFiles)) { + // return $this->response->setJSON([ + // 'status' => 'error', + // 'message' => 'No zip files uploaded', + // ]); + // } + + // // -------------------------------------------------------- + // // 1) Pre-process distribution IDs → group by distribution + // // - So we can run ONE invalidation per distribution + // // - And merge all paths into a single JSON array + // // -------------------------------------------------------- + // $distGroups = []; // [distId => ['indexes' => [...], 'paths' => [...], 'firstIndex' => int]] + + // foreach ($cfDistributions as $i => $distId) { + // $distId = trim((string) $distId); + // $path = trim((string) ($cfPathsList[$i] ?? '')); + + // // Only consider entries where both distribution ID and path are set + // if ($distId === '' || $path === '') { + // continue; + // } + + // if (!isset($distGroups[$distId])) { + // $distGroups[$distId] = [ + // 'indexes' => [], + // 'paths' => [], + // ]; + // } + + // $distGroups[$distId]['indexes'][] = $i; + // $distGroups[$distId]['paths'][] = $path; + // } + + // // Set firstIndex and unique paths per distribution + // foreach ($distGroups as $distId => $info) { + // $distGroups[$distId]['firstIndex'] = $info['indexes'][0]; // first file index for this dist + // $distGroups[$distId]['paths'] = array_values(array_unique($info['paths'])); // unique paths + // } + + // // -------------------------------------------------------- + // // 2) Process each uploaded file + // // -------------------------------------------------------- + // foreach ($zipFiles as $index => $file) { + // if (!$file->isValid() || $file->hasMoved()) { + // $results[] = [ + // 'file' => $file->getName(), + // 'status' => 'error', + // 'message' => 'Invalid file or already moved.', + // ]; + // continue; + // } + + // // Read matching form values (or fallback) + // $zipFolder = $zipFolders[$index] ?? 'web/'; // default example + // $s3Bucket = $s3Buckets[$index] ?? ''; + // $s3Prefix = $s3Prefixes[$index] ?? ''; + // $cfDistribution = $cfDistributions[$index] ?? ''; + // $cfDistribution = trim((string) $cfDistribution); + + // // Move file into a known directory (keep original name) + // // $uploadDir = WRITEPATH . 'uploads/deploy'; + // $uploadDir = '/home/ubuntu/py'; + // if (!is_dir($uploadDir)) { + // mkdir($uploadDir, 0775, true); + // } + + // $originalName = $file->getName(); + // $file->move($uploadDir, $originalName); + // $zipPath = $uploadDir . DIRECTORY_SEPARATOR . $originalName; + + // // -------------------------------------------------------- + // // Decide whether THIS file should trigger invalidation + // // - Only firstIndex of each distribution will do it + // // - cf-paths-json = JSON array of all unique paths for that dist + // // -------------------------------------------------------- + // $doInvalidation = false; + // $cfPathsJson = ''; + + // if ($cfDistribution !== '' && isset($distGroups[$cfDistribution])) { + // $group = $distGroups[$cfDistribution]; + + // if ($group['firstIndex'] === $index) { + // // This is the first file for this distribution ID → do invalidation ONCE + // $doInvalidation = true; + + // // Build CloudFront paths JSON array (AWS syntax: ["path1", "path2", ...]) + // $cfPathsJson = json_encode($group['paths']); // e.g. ["\/hr\/*","\/hr\/special\/*"] + // } + // // Else: same distribution ID but NOT first index → no invalidation + // } + + // // -------------------------------------------------------- + // // Build the python command safely using escapeshellarg + // // -------------------------------------------------------- + // $cmdParts = [ + // escapeshellarg($pythonBin), + // escapeshellarg($scriptPath), + // '--zip-path', escapeshellarg($zipPath), + // '--zip-folder', escapeshellarg($zipFolder), + // '--s3-bucket', escapeshellarg($s3Bucket), + // '--s3-prefix', escapeshellarg($s3Prefix), + // '--do-webhook', // always send webhook after success + // ]; + + // if ($doInvalidation) { + // $cmdParts[] = '--do-invalidation'; + // $cmdParts[] = '--cf-distribution-id'; + // $cmdParts[] = escapeshellarg($cfDistribution); + // $cmdParts[] = '--cf-paths-json'; + // $cmdParts[] = escapeshellarg($cfPathsJson); // e.g. '["/hr/*","/hr/special/*"]' + // } + + // // Final command string (2>&1 to capture stderr too) + // $cmd = implode(' ', $cmdParts) . ' 2>&1'; + // print_r($cmd);die(); + // $output = []; + // $returnVar = 0; + + // exec($cmd, $output, $returnVar); + + // $results[] = [ + // 'file' => $originalName, + // 'zip_path' => $zipPath, + // 'command' => $cmd, + // 'output' => $output, + // 'exit_code' => $returnVar, + // 'status' => $returnVar === 0 ? 'success' : 'error', + // ]; + // } + + // return $this->response->setJSON([ + // 'status' => 'completed', + // 'results' => $results, + // ]); + // } + + public function fedeploy() + { + $request = $this->request; + + // Single zip file: + $file = $request->getFile('zip_file'); + + if (!$file || !$file->isValid()) { + return $this->response->setJSON([ + 'status' => 'error', + 'message' => 'No valid zip file uploaded', + ]); + } + + // Read scalar form values + $zipFolder = (string) $request->getPost('zip_folder') ?: 'web/'; + $s3Bucket = (string) $request->getPost('s3_bucket') ?: ''; + $s3Prefix = (string) $request->getPost('s3_prefix') ?: ''; + $cfDistribution = trim((string) $request->getPost('cf_distribution_id')); + $cfPathsRaw = (string) $request->getPost('cf_paths'); + + // Python interpreter and script path from env + $pythonBin = getenv('PY_PATH'); // e.g. /usr/bin/python3 + $scriptPath = getenv('PY_SCRIPT_PATH'); // e.g. /home/ubuntu/deploy_assets.py + + if (empty($pythonBin) || empty($scriptPath)) { + return $this->response->setJSON([ + 'status' => 'error', + 'message' => 'Python path or script path not configured in environment.', + ]); + } + + // Move file into known directory (keep original name) + $uploadDir = '~/py'; + if (!is_dir($uploadDir)) { + mkdir($uploadDir, 0775, true); + } + + $originalName = $file->getName(); + $file->move($uploadDir, $originalName); + $zipPath = $uploadDir . DIRECTORY_SEPARATOR . $originalName; + + // ----------------------------- + // CloudFront invalidation data + // ----------------------------- + $doInvalidation = false; + $cfPathsJson = ''; + + // Allow comma or newline separated paths: "/hr/*,/hr/special/*" or + // "/hr/*\n/hr/special/*" + $paths = array_filter( + array_map('trim', preg_split('/[\r\n,]+/', $cfPathsRaw)), + 'strlen' + ); + + if ($cfDistribution !== '' && !empty($paths)) { + $doInvalidation = true; + $cfPathsJson = json_encode($paths); // e.g. ["\/hr\/*","\/hr\/special\/*"] + } + + // ----------------------------- + // Build python command + // ----------------------------- + $cmdParts = [ + escapeshellarg($pythonBin), + escapeshellarg($scriptPath), + '--zip-path', escapeshellarg($zipPath), + '--zip-folder', escapeshellarg($zipFolder), + '--s3-bucket', escapeshellarg($s3Bucket), + '--s3-prefix', escapeshellarg($s3Prefix), + '--do-webhook', // always send webhook after success + ]; + + if ($doInvalidation) { + $cmdParts[] = '--do-invalidation'; + $cmdParts[] = '--cf-distribution-id'; + $cmdParts[] = escapeshellarg($cfDistribution); + $cmdParts[] = '--cf-paths-json'; + $cmdParts[] = escapeshellarg($cfPathsJson); + } + + // Final command string (2>&1 to capture stderr too) + $cmd = implode(' ', $cmdParts) . ' 2>&1'; + $output = []; + $returnVar = 0; + print_r($cmd);die(); + exec($cmd, $output, $returnVar); + + $result = [ + 'file' => $originalName, + 'zip_path' => $zipPath, + 'command' => $cmd, + 'output' => $output, + 'exit_code' => $returnVar, + 'status' => $returnVar === 0 ? 'success' : 'error', + ]; + + return $this->response->setJSON([ + 'status' => 'completed', + 'result' => $result, + ]); + } + + + public function fedeploy_view() + { + // $this->load->view('fedeploy'); + $this->loadLayout('fedeploy'); + } + +} diff --git a/app/Views/fedeploy.php b/app/Views/fedeploy.php new file mode 100644 index 00000000..906bf5f7 --- /dev/null +++ b/app/Views/fedeploy.php @@ -0,0 +1,43 @@ +