Last active
May 16, 2023 09:07
-
-
Save myh-st/47fbce4d9a85d6a9e64add9da4ce7d53 to your computer and use it in GitHub Desktop.
Revisions
-
myh-st revised this gist
May 16, 2023 . 1 changed file with 0 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,10 +1,3 @@ เขียน aws cdk ในการเชื่อมต่อ git codcommit เพื่อทำ ci/cd aws glue ประมาณ 3 jobs ## Genie -
myh-st renamed this gist
May 16, 2023 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
myh-st created this gist
May 16, 2023 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,241 @@ --- Crafted by [Genie](https://marketplace.visualstudio.com/items?itemName=genieai.chatgpt-vscode) --- ## You เขียน aws cdk ในการเชื่อมต่อ git codcommit เพื่อทำ ci/cd aws glue ประมาณ 3 jobs ## Genie ตัวอย่างการใช้ AWS CDK สำหรับการเชื่อมต่อ Git CodeCommit และสร้าง CI/CD pipeline สำหรับ AWS Glue ที่ประกอบด้วย 3 jobs: 1. สร้างไฟล์ `cdk.json` ที่รากของโปรเจคของคุณ (ถ้ายังไม่มี) และตั้งค่าคำสั่งเริ่มต้นสำหรับ CDK: ```json { "app": "npx ts-node --prefer-ts-exts infra/app.ts" } ``` 2. สร้างไดเรกทอรี `infra` และสร้างไฟล์ `infra/app.ts` ดังนี้: ```typescript import * as cdk from 'aws-cdk-lib'; import { PipelineStack } from './pipeline-stack'; const app = new cdk.App(); new PipelineStack(app, 'PipelineStack'); ``` 3. สร้างไฟล์ `infra/pipeline-stack.ts` ที่มีโค้ดต่อไปนี้: ```typescript import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import * as codecommit from 'aws-cdk-lib/aws-codecommit'; import * as codepipeline from 'aws-cdk-lib/aws-codepipeline'; import * as codepipeline_actions from 'aws-cdk-lib/aws-codepipeline-actions'; import * as glue from 'aws-cdk-lib/aws-glue'; import * as iam from 'aws-cdk-lib/aws-iam'; export class PipelineStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // Create a CodeCommit repository const repo = new codecommit.Repository(this, 'GlueJobsRepo', { repositoryName: 'glue-jobs-repo', }); // Create a CodePipeline const pipeline = new codepipeline.Pipeline(this, 'GlueJobsPipeline', { pipelineName: 'glue-jobs-pipeline', }); // Add source stage to the pipeline const sourceOutput = new codepipeline.Artifact(); const sourceAction = new codepipeline_actions.CodeCommitSourceAction({ actionName: 'CodeCommit_Source', repository: repo, output: sourceOutput, }); pipeline.addStage({ stageName: 'Source', actions: [sourceAction], }); // Add deploy stage to the pipeline const deployAction = new codepipeline_actions.AwsLambdaInvokeAction({ actionName: 'Deploy_Glue_Jobs', lambda: this.createDeploymentFunction(), userParameters: { glueJobNames: ['job1', 'job2', 'job3'], }, }); pipeline.addStage({ stageName: 'Deploy', actions: [deployAction], }); } private createDeploymentFunction(): lambda.Function { // Create an IAM role for the Lambda function const role = new iam.Role(this, 'DeploymentFunctionRole', { assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), }); role.addToPolicy( new iam.PolicyStatement({ actions: [ 'glue:CreateJob', 'glue:UpdateJob', 'glue:DeleteJob', 'glue:GetJob', ], resources: ['*'], }) ); // Create the Lambda function return new lambda.Function(this, 'DeploymentFunction', { runtime: lambda.Runtime.NODEJS_14_X, handler: 'index.handler', code: lambda.Code.fromAsset(path.join(__dirname, 'deployment-function')), role: role, }); } } ``` 4. สร้างไดเรกทอรี `infra/deployment-function` และสร้างไฟล์ `infra/deployment-function/index.js` ที่มีโค้ดต่อไปนี้: ```javascript const AWS = require('aws-sdk'); const glue = new AWS.Glue(); exports.handler = async (event) => { const jobNames = event.userParameters.glueJobNames; for (const jobName of jobNames) { await createOrUpdateGlueJob(jobName); } }; async function createOrUpdateGlueJob(jobName) { try { await glue.getJob({ JobName: jobName }).promise(); console.log(`Updating Glue job: ${jobName}`); // Update the job with new settings } catch (error) { if (error.code === 'EntityNotFoundException') { console.log(`Creating Glue job: ${jobName}`); // Create the job with initial settings } else { throw error; } } } ``` 5. ติดตั้ง dependencies ของ CDK และ TypeScript ด้วยคำสั่ง: ```bash npm install aws-cdk-lib constructs typescript ts-node ``` 6. สั่งให้ CDK สร้าง stack ด้วยคำสั่ง: ```bash npx cdk deploy ``` โค้ดด้านบนจะสร้าง CodeCommit repository และ CodePipeline ที่มี 2 stages: Source และ Deploy. ในขั้นตอนการ Deploy, Lambda function จะถูกเรียกใช้เพื่อสร้างหรืออัปเดต Glue jobs ตามที่ระบุใน `userParameters`. คุณสามารถปรับแต่งโค้ดใน `createOrUpdateGlueJob` เพื่อกำหนดค่าต่าง ๆ สำหรับ Glue jobs ของคุณ. ## You แล้ว code ของแต่ละ job ที่มี .py นั้นต้องเก็บไว้ที่ไหน ## Genie คุณสามารถเก็บไฟล์ `.py` ของแต่ละ job ในโฟลเดอร์ที่อยู่ใน CodeCommit repository ที่เราสร้างขึ้นก่อนหน้านี้ (ชื่อว่า `glue-jobs-repo`) โดยสามารถจัดระเบียบโค้ดของ Glue jobs ตามโครงสร้างโฟลเดอร์ที่คุณต้องการ ตัวอย่างเช่น: ``` glue-jobs-repo/ ├── job1/ │ └── job1.py ├── job2/ │ └── job2.py └── job3/ └── job3.py ``` เมื่อคุณมีโค้ดของ Glue jobs ใน repository แล้ว คุณต้องปรับแต่ง Lambda function ใน `infra/deployment-function/index.js` เพื่ออ่านไฟล์ `.py` และส่งค่าให้กับ Glue jobs ที่ถูกสร้างหรืออัปเดต คุณสามารถทำได้ดังนี้: 1. ใน `infra/pipeline-stack.ts`, ปรับแต่ง `userParameters` ใน `AwsLambdaInvokeAction` โดยเพิ่มพารามิเตอร์ `jobScriptPaths`: ```typescript const deployAction = new codepipeline_actions.AwsLambdaInvokeAction({ actionName: 'Deploy_Glue_Jobs', lambda: this.createDeploymentFunction(), userParameters: { glueJobNames: ['job1', 'job2', 'job3'], jobScriptPaths: ['job1/job1.py', 'job2/job2.py', 'job3/job3.py'], // Add this line }, }); ``` 2. ใน `infra/deployment-function/index.js`, ปรับแต่งฟังก์ชัน `handler` ให้รับพารามิเตอร์ `jobScriptPaths` และส่งค่าให้กับฟังก์ชัน `createOrUpdateGlueJob`: ```javascript exports.handler = async (event) => { const jobNames = event.userParameters.glueJobNames; const jobScriptPaths = event.userParameters.jobScriptPaths; for (let i = 0; i < jobNames.length; i++) { await createOrUpdateGlueJob(jobNames[i], jobScriptPaths[i]); } }; ``` 3. ปรับแต่งฟังก์ชัน `createOrUpdateGlueJob` ใน `infra/deployment-function/index.js` เพื่อรับพารามิเตอร์ `jobScriptPath` และใช้ค่านี้เมื่อสร้างหรืออัปเดต Glue job: ```javascript async function createOrUpdateGlueJob(jobName, jobScriptPath) { // ... (existing code) // Replace the existing try block with the following: try { await glue.getJob({ JobName: jobName }).promise(); console.log(`Updating Glue job: ${jobName}`); // Update the job with new settings and script path await glue.updateJob({ JobName: jobName, JobUpdate: { Command: { ScriptLocation: `s3://your-bucket-name/${jobScriptPath}`, }, }, }).promise(); } catch (error) { if (error.code === 'EntityNotFoundException') { console.log(`Creating Glue job: ${jobName}`); // Create the job with initial settings and script path await glue.createJob({ Name: jobName, Role: 'your-glue-job-role-arn', Command: { Name: 'glueetl', ScriptLocation: `s3://your-bucket-name/${jobScriptPath}`, }, }).promise(); } else { throw error; } } } ``` อย่าลืมแทนที่ `'your-bucket-name'` และ `'your-glue-job-role-arn'` ด้วยชื่อของ S3 bucket และ ARN ของ IAM role ที่ใช้กับ Glue jobs ของคุณ เมื่อคุณทำตามขั้นตอนด้านบนแล้ว โค้ดของ Glue jobs จะถูกอ่านจากไฟล์ `.py` ใน CodeCommit repository และส่งค่าให้กับ Glue jobs ที่ถูกสร้างหรืออัปเดต