From f8dd59a09b45a6d5272fe289fe2b40cd9e67dc03 Mon Sep 17 00:00:00 2001 From: Andrew Gearhart Date: Thu, 4 Sep 2025 23:39:31 -0400 Subject: [PATCH 1/2] Remove unnecessary .DS_Store files from the repository --- .DS_Store | Bin 10244 -> 0 bytes .gitignore | 3 ++- javascript_docker/.DS_Store | Bin 6148 -> 0 bytes lambda/.DS_Store | Bin 6148 -> 0 bytes lambda/java_lambda/PDFMergerLambda/.DS_Store | Bin 6148 -> 0 bytes .../java_lambda/PDFMergerLambda/src/.DS_Store | Bin 6148 -> 0 bytes .../PDFMergerLambda/src/main/.DS_Store | Bin 6148 -> 0 bytes .../PDFMergerLambda/src/main/java/.DS_Store | Bin 6148 -> 0 bytes .../PDFMergerLambda/src/main/java/com/.DS_Store | Bin 6148 -> 0 bytes .../src/main/java/com/example/.DS_Store | Bin 6148 -> 0 bytes .../PDFMergerLambda/src/test/.DS_Store | Bin 6148 -> 0 bytes .../PDFMergerLambda/src/test/java/.DS_Store | Bin 6148 -> 0 bytes .../PDFMergerLambda/src/test/java/com/.DS_Store | Bin 6148 -> 0 bytes 13 files changed, 2 insertions(+), 1 deletion(-) delete mode 100644 .DS_Store delete mode 100644 javascript_docker/.DS_Store delete mode 100644 lambda/.DS_Store delete mode 100644 lambda/java_lambda/PDFMergerLambda/.DS_Store delete mode 100644 lambda/java_lambda/PDFMergerLambda/src/.DS_Store delete mode 100644 lambda/java_lambda/PDFMergerLambda/src/main/.DS_Store delete mode 100644 lambda/java_lambda/PDFMergerLambda/src/main/java/.DS_Store delete mode 100644 lambda/java_lambda/PDFMergerLambda/src/main/java/com/.DS_Store delete mode 100644 lambda/java_lambda/PDFMergerLambda/src/main/java/com/example/.DS_Store delete mode 100644 lambda/java_lambda/PDFMergerLambda/src/test/.DS_Store delete mode 100644 lambda/java_lambda/PDFMergerLambda/src/test/java/.DS_Store delete mode 100644 lambda/java_lambda/PDFMergerLambda/src/test/java/com/.DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 7b405380ecfbc05a9af8ad0cc6879f97c551fa75..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10244 zcmeHM&2Jk;6n|Sg$vUBt5kd5Vv{Elf7~_19rV0n+x#+ zM6v`zqWlLOdMK4RBH#d#xFA%H9MeV2GMz#w1{FbEg~ z3<3s${|f^6X7ggtNNQSxfI+|@aEt)Y4-P7)Sw(x2iqwHd905S%7#0QnB=3Maie?q< zNs1X1ONxR@QA-^$EGdq0NAYD9?MW)d$x??8OYLl_6N)8v$NG+7Co3zdX$=Affqn$| z**#8aDpQ48`uW{HOntA<)mT1Xs<8z5^l$C_@Je{z8#!O!KDisPA8taFrm*iG zHED|&dF1Q6V|KNlL)YPh_dYq&A+k=5ooF(gOV>x`tVwdIj=wbOyRTK*ma>`E^M<-q2;#P&79k~#-FY*RxKU%-O`&Czf(-kU1CAYtpt8U2vj^DEN^X80*`fa ztQ~kwAzP3WcEU~+ljpkKh2>1jSzKD#PdVL-3+OK`F7NLr?5EGaxVm24t=0l|gM)$3 zzWVoo&dTTGmdElKmg=6Le)-bv@uYPBf9BnPw01-Ie~kU~DEMcRdMwP`b-1Bp?6+5F z1XUK4!OfAHq$(n(MkU0H8;KK+m>wq~UM(WN{?{YonQr&Oa>|*{ER6_=kDxxv(173p z6EaD6ef-y7-jB}fPWEG8th_Fr99lzn=P(}KaTBvyY!lWa;-Unt(`9^q^7IC18qV^< zj^dvtYgS8bb4Z3hT}Lvkh+Yj(0g^(KUVxi@B#Shj-ifAro+3l*B!{juP@X52ko>gx z1huis7IsY|$lU0j7J@7!!_hFsAYc$M2p9wm0tSIoL?9;Dc4j~?5C8rD6g4nQ8w3mj z|1| mV_b-X3UN?*n}2FQ2Jkz_fp;bPA<&%v&G}!u9(l~p|9=4;_u~=( diff --git a/.gitignore b/.gitignore index 62a3f489..73816f18 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,5 @@ cdk.out/ __pycache__/ *.pyc javascript_docker/node_modules -lambda/add_title/venv \ No newline at end of file +lambda/add_title/venv +.DS_Store diff --git a/javascript_docker/.DS_Store b/javascript_docker/.DS_Store deleted file mode 100644 index 09bb7e5ab9566d56814246ba16ddf79fdad78308..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKJ5Izf5S@W7B9>xHN?&1Xny?Bd*lrupk_dznvJ%?fN1&$U3fzGsAaNVseE38} zD?xz}nvv``wr9qZC&l&<5ihp&oM=Ww1)3m>G9ofPy0quU6Ci7hGwP_Pnzq!A1p13p zlKUauXx0sV&cC7C_Hw?w=(~+1esKJ<+GX4IRkd#WHEfF2<9+jR{dBV1zW$c|=ISGt z>GK^zhXez`Krj#t1Oq=}0C%=XF*S@n7zhS}fp-Svd`M`5rDHbKqXV6m06=+0t3a1p zLVS{A>6i_%0%3Cnnk##W!RC(nb5HKV0-rc2ji7l8As_sR1zjt@<-Jjp{-Q@s)^~b>mKpOxIOoYuf z%qoQ1DJ{v0sv&14`Y0fR0%8c`?Imknp&8H&{BI1<-ZjC40Dms--NXI6;XLI@M$>J) zy8oftD&d2HA9EjDjSKTH-|o#n-mbF@{?anrDUJM2OrQn3IKw?mE}ktOB;ez0J%5sC zYV`Mh7Dsu}?S5t}jpnJ-tH!F)GKS6$pE!kAjPt%X+M?1!&SQU}d;X&+oVe|?cX(QO zQ5uefLllH)@^~{!13u~VaT?^p*O3i|X_#(%eLC%3ztORJSFY`Mtm(~Ow_{yJecv?B zUAlbhf%`m8Qa(pEP#B($Le3~$z)MtWRu^v{@xZoz;#pm1S&qW+`|I${u82ZSzX?Bz z#GkFp(O^R{?V5h~oKYI{l+JxxtqD0~7%lpqT+{-1c0%G+v9fZk0M5UtUVk}G7Y{xy z;#ARJIYw{4{#ZNMRQqa)({g+OY#g|X`QKtgRwU}HG+MH#bIpKeKr?X20G$sOCPG`` zOrkhCFcVJz#3oh?L7o0mkdLL%RydQ0EhtR7B1%`Lo)}EJW4)#9Y=tw4(jAx>8T(Nq zGxb7YVsxyxggG!)+-J*y}x|@V_akCS$n??wMy{aF= zkKoa}2S0&$^VF+nJ?eWi6U-*92ciCBUU>7Ho%d%mzqdQH0|2Zs>XZNq0AQgKX3t`C zjF6plNmld-1v8oBIrJg87l^hOEP0y&!+>GnZ)1So-5d-+;G4SzbMLS4&_dRms9WEp zU=QGO+8d)H@L&_Q3T>!>jXnBpf(wr@;~f~y)`VG3_G%$#26GIdtyYei7rZ&%%Ns`n zFOXhuy+Pndv2A~3E1B$>)tr^H)~u(_ffzfn8;_!fJA6!6dqM=>tnYdc{O-6_SidF0 z*!9EiPzLy&F1kE<=!YFKZirFXiDay!3|8LCw+b7RNwr$!6y^_-w{ed!l`1-@r7tN-gruF*Eo~Z7= zr&8#+zUchKIyjii%4|xm;|`r+7>KZkBlPc9A;vNdp$A=v)AX||XrC{9%J)wfVW(E) zrCOPaP`hqpLAEQuP=wT!Ql&V$kzJ%`z92{EFTMM8R~96dW4(&!s!CxPpg zlh6O@Aai9HFbw=x46tm|X*O_5dT(8t9PPCnbsv?4{1SyS1RK2_%MNYD7g434jZ+7) Vt}#)FBPixWK+<3u!@zH4;5)sk`DFkA diff --git a/lambda/java_lambda/PDFMergerLambda/src/.DS_Store b/lambda/java_lambda/PDFMergerLambda/src/.DS_Store deleted file mode 100644 index a5bd613efd27c389110306acca2ae7c2612de4d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKF>ljA6uxT>b*MlYKy!`7?eNpT*gB8guF!2wN z7#JC0WI|$O;Xm*z;Jv#S%T8M)mI~2((%pByckj;c`*c1ZV~qD_!8T(}#+V5O(YOTF z35I?w$83#yt^jhJ<9;L#{7Crlj1y|p3}^=aZ3b}f8Z2fW3t6(VfA_(6^OrQ4L^;l% zrxV)epZrM_rdhlFgRiX{7cOp?8|J3@+#QR#n|awR?R(Rw`1DAK$X~WS|8Y2)51Uu- ziX`*GWHgllVK9Or&z^)yAm)8BOM+C!y2@cT%*L>JJe^V+IK64qi^1NfW zf&1<*>TtUQ?e31fq66{_cB&3pDoO%XL?D zkZ*h*D%u?8=6Og~=cpOb4Ez-X_EGU3U#d+&(9zNy%Uk}nxngPwgf5iYd2JWB_Dbd+_EIB-DEhsObpy9Yep$vhFj$_%tqj(F7 bH1Jv20CWfoh0p`0e*`2Ay3!1sDFeR&e0bI# diff --git a/lambda/java_lambda/PDFMergerLambda/src/main/.DS_Store b/lambda/java_lambda/PDFMergerLambda/src/main/.DS_Store deleted file mode 100644 index b372101e7ef2668502e209bec117fc0323269277..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKOG^VW5Kd~fDI)Zs=yAbo(N>E^ysWhzJa}!l{07Xn?q4_}2kNQqh#*zW#ILA&X z&%IE3FvbZCSTz13UH|MtrzNHr>Y9mRU*K0S;Ip2HDFlcuQg=e0cNKZ~> zL`F=DQ|D6loQ~V+wkvMy7)Se3hTgF6dIv$hSIf2I+Cx=1g%U(rx zBfqV39qkZVk*($C`~7k`Z>^R}gS^#WUn%6R((2k^kQH-_%Nu*O>#z~YTg^O&zon8H zgG0E3PO_cwqUfBD4RNi<*T9Vv`^uP2sFGuH&afu}N#%V>N zj4r@7{GI40AqI#6V&K~uFqe*){`Qq<0b+m{_-hQ{{a}G2+6H5d>gs?-l>mTgFe`z+ z`t%31&;V!~j5UG5QwDVIH$GHx&vug$K7(IODcP zYKZ}2V4Q&oJf-kEzmPi6pV{CCMnQS iPcg*eQ@jAG1nd@e0BwV@MzDa;hk&Ai8e-r_8F&Rhj&G#^ diff --git a/lambda/java_lambda/PDFMergerLambda/src/main/java/.DS_Store b/lambda/java_lambda/PDFMergerLambda/src/main/java/.DS_Store deleted file mode 100644 index 31a22390d8c7998e7450171e7b107ef9fe75c141..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK&2Abo5VnC9BNT~4tLC^;uc#pb6;)ieTYAW~8?}cfA}otw+ub!{p&Ss>UXvHf zvC5@VU!bqk%-BO4M3N&)s~Kth+4E!L&&b{pLP&2O9tu$tLMTwgLIs*T1pTO6QXoqi zP~seV5X3rw5l+YQFED^-R}=%GMRFW(oZnmUy!vg#Y=okMMK+;Rz6vIBl+7BAU$Rgv zJ$YJIWmQ#Y{#Y;kS${Uqy#Dkvj!v|WgLS_je2j*RUhUaCozD7EI-Ht>C>%n_>8B_S z^}^HhG|Wt{Zyl0gWjE083yt z0)6xG59pu)&?U?*f(1m{R6v_5sl<>}J4l-jewX5Ni#AD@&?SB$Xc0G2ueG z7P(~xn1M|OigsAT_y7I<_5WrPkC*{w;J;!(mb!k|gDuh9y0tlcYaP&YP!x>IE&fS? jj(Lh97N6pMP$OV>umk84<`%&M!XE;L25y*voicC(wOnmX diff --git a/lambda/java_lambda/PDFMergerLambda/src/main/java/com/.DS_Store b/lambda/java_lambda/PDFMergerLambda/src/main/java/com/.DS_Store deleted file mode 100644 index 1c0d8869302d6d6cfc08deaa90692d5513855e82..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK&2AGh5FV$2II56x0MVl*ZYYA3MpTH)5`wB;Sp)})!ftofuJEo``5~2}h~)?` z&@)fbH{cPt@hmW7JE+ZqgnB@znvuqzJ^sdCf4j2R03ZglWE-FZ01}ki)t6XJYK3&*BOCy&u-FR%6HWNf~R) zK8s78O{TrxH__N=Uc26sEx9S*gvVwcPNV5;GKj{nsrAAb9k1$9{4z`Dqt4BzrkF-q zk&bObmZV5Ic$F22nGejYNG3KnbRDuS+oR6y#bS52t9JVRWmhd8J?M2+f9K(H*_OBN z+<*Lh^iJo6`D7m(1b(8{Zg^b5XRNGAppUl0Lz9<|a`&Ll$jxx*mn~1feE9f%?<)zl zHcoDmzhITe=VuFO(zS8khvPz<;s|?Is~{E|E5Hh{0+&?4ZzXc`lKGs*3a|oKR{`1| z6gpwxv2tj)4lL{y0I`W-YgnhBM#@nh1CNzM>_HPQ715;%f5i|k9plRL0*{qLmkz>T zK7^lH_#29_v*Y;6(m@0cxnu=cfr|=kxMqjW|7U-`|6fev7AwFCTqy-aa~KW>xFmnJ z))q%+twMi`PDZ@S;ja{|*rOP^bQEu)Tf?}b3S!`~a)=Q${t>V;aKQ@vQw4qkUE6wU diff --git a/lambda/java_lambda/PDFMergerLambda/src/main/java/com/example/.DS_Store b/lambda/java_lambda/PDFMergerLambda/src/main/java/com/example/.DS_Store deleted file mode 100644 index 0e4489edc37e370c5f48577550069a577fe25a46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKF-`+P475p#lW0;>?h7LEgH4nasrdj2R47ttpuUQC@iUmQt%&HLLNsW6^3JZ; zb9*<%`D|vsetEn#TbS7ZC)yi_sd1k^v8#$W5RQ91+1_4lzdN2DCfVNy$Q^8D&$yOf z`G@1_fIU9g3cmaZ!%QXxq<|EV0#ZN<{6+!RUf6J*s8I??0V!}+fZvA(C-%ZIF+Lp_ zq6GlX5e~yVdI?}-0N4x1L_}boRA5rQS`1G*;;r&};h30o^Eeszsgu1r6pzypZ;@`^ z6E#W!DR8O4ESC$`|1JE7{{NDsl@yQy|4IR$Z|*j0yi(QH$;+|UHuyc9Iqz^9=0U*_ lu;n@GyM#yR$T;g}e7#Dfmh&j59iNrAss;1kTc8&3cL diff --git a/lambda/java_lambda/PDFMergerLambda/src/test/.DS_Store b/lambda/java_lambda/PDFMergerLambda/src/test/.DS_Store deleted file mode 100644 index 103cb6ef816d3126245f381ac6374b3947d2cd65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKOG^VW5Kd~fDI)Zs(Bp#FqO}!K^sv@?@FuS4L8b1xMOU|*(&wQR_9o~b^5)IE z7ypjVB@dc7rRy&-mScA0P4yW+Nvu(vN|=#6aGI|%CiT5fhrMjbbZ>MfNJ_;na^d>BN&>{nzr z^4luc(E*Va*;+0?7?f6u1*^QgIxJX&wG!CN<(1(uE9T}G*Y|2yVIz_^ntBfZOC>V~ zM{o;9vY+sL$vKmarVf^_U&k7iG5LzT()y#i zvGnF`S(Vj>`sttP%%AqBvq`5v{(-$Ct>a*6_k-hTnDwfgUvxU{N9k~E5~6SjLr%U& zX{fV~o~7Z$m@%iVFBd!H6N&ir!&?7e1dv8br`+q>;=z4JIp^>0hO zg#VPDVDgb@>=cbhk_UR3BQmjs5lwGD3NY4*wAyo&7zli<48{ zg+ESXot}bc`Rg#s!VEA2%)ojXpc_bStan*njTvADUI7DmKRBR>9${|LTpiGu5&*CS zZX;lukAFZ19e^HTZV@~n(xw91R7oX|1R lq<~?bVi=20aShZ6_#HF=J;K}~ctH3=z|g=AGq6?${s80)YPA3W diff --git a/lambda/java_lambda/PDFMergerLambda/src/test/java/com/.DS_Store b/lambda/java_lambda/PDFMergerLambda/src/test/java/com/.DS_Store deleted file mode 100644 index 5ac6743462be2e7fa38fadfe0ba9741a69db12f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK&2G~`5S~o~*{DLw0i+%+ajhWzQ33U0LO5{62o8XPU0bci+H2*fL5d=LZr_4u z;J_2`2)qW505h{2)W#s89uTT#q}gvg`^~QRv*q;yfEvuw9e^GHXmr9>7n|Q0^^-TO zI{b0kW!A|CrDlyFd zl2j(2O#A(BsaE%q9??Zr2 z7<#N7@}~nEJ^~=NG0lcC|Gyvxlt2tU)($a)rd%naD^>o8pJ=*`D{`vfWxk#==0a4&uDWKZJXgI(n`MtHV xINECi^mpiF#H$_tD#3uaV&u|RyoJt&`G5k%&|~coGidT7z%oc93j9+AegbYMdG7!K From 4dcb0f5b5609ec0f3fad43739f3930559226af59 Mon Sep 17 00:00:00 2001 From: Andrew Gearhart Date: Thu, 4 Sep 2025 23:40:05 -0400 Subject: [PATCH 2/2] Enhance environment-aware configuration and naming conventions across the project - Updated README.md to include environment and naming guidelines for multi-environment deployments. - Modified app.py to support environment-specific naming for resources and tags. - Adjusted Dockerfiles to remove hardcoded AWS region and rely on task execution environment. - Refactored secret retrieval in autotag.py and main.py files to use dynamic naming based on environment variables. - Updated JavaScript files to utilize environment variables for AWS region configuration. --- README.md | 48 ++++++-- app.py | 116 ++++++++++++++---- docker_autotag/Dockerfile | 3 +- docker_autotag/autotag.py | 8 +- javascript_docker/Dockerfile | 3 +- javascript_docker/alt-text.js | 2 +- .../main.py | 2 +- .../main.py | 2 +- 8 files changed, 136 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 5917ba8e..6986105f 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,31 @@ Ensure your project has the following structure: |__ client_credentials.json (The client id and client secret id for adobe) ``` +## Environment and Naming + +This project supports environment‑aware stack and resource naming to simplify multi‑env deployments. + +- name_prefix: Computed as `-` (defaults: `stackBase=pdfaccessibility`, `env=dev`). +- CloudFormation stack: Named `-` unless overridden via `stackName`. +- S3 bucket: Named `---` (globally unique; lowercase and hyphenated). +- ECS cluster: Named `-cluster`. +- Step Functions: Log group `/aws/states/-state-machine` and state machine name `-state-machine`. +- CloudWatch dashboard: Named `PDF_Processing_Dashboard_`. + +Common deploy patterns: + +- Minimal (uses active AWS profile for account/region): + - `cdk deploy -c env=dev` +- Specify env and base: + - `cdk deploy -c env=prod -c stackBase=pdfrem` +- Force an exact stack name: + - `cdk deploy -c stackName=pdfrem-bgdev` + +Account/Region inference: + +- You do not need to set `CDK_DEFAULT_ACCOUNT`/`CDK_DEFAULT_REGION`. If not provided, CDK uses the credentials of your current AWS CLI profile to infer them at deploy time. +- If you prefer to pin them, pass `-c account= -c region=` or export environment variables. + ## Setup and Deployment 1. **Clone the Repository**: @@ -79,10 +104,7 @@ Ensure your project has the following structure: ```bash aws configure ``` - - Make sure the region is set to - ``` - us-east-1 - ``` + - Make sure a default region is set (example: `us-east-1`). The CDK will use your configured profile's region unless you explicitly pass one via `-c region=...`. 3. **Set Up CDK Environment**: - Bootstrap your AWS environment for CDK (run only once per AWS account/region): @@ -103,29 +125,29 @@ Ensure your project has the following structure: - Replace and with your actual Client ID and Client Secret provided by Adobe and not the whole file. 5. **Upload Credentials to Secrets Manager**: - - Run this command in the terminal of the project to push the secret keys to secret manager: + - Run this command in the terminal of the project to push the secret keys to Secrets Manager (namespaced by project/env): - For Mac ``` aws secretsmanager create-secret \ - --name /myapp/client_credentials \ + --name ///client_credentials \ --description "Client credentials for PDF services" \ --secret-string file://client_credentials.json ``` - For Windows ```bash - aws secretsmanager create-secret --name /myapp/client_credentials --description "Client credentials for PDF services" --secret-string file://client_credentials.json + aws secretsmanager create-secret --name ///client_credentials --description "Client credentials for PDF services" --secret-string file://client_credentials.json ``` - Run this command if you have already uploaded the keys earlier and would like to update the keys in secret manager. - For Mac: ``` aws secretsmanager update-secret \ - --secret-id /myapp/client_credentials \ + --secret-id ///client_credentials \ --description "Updated client credentials for PDF services" \ --secret-string file://client_credentials.json ``` - For Windows: ```bash - aws secretsmanager update-secret --secret-id /myapp/client_credentials --description "Updated client credentials for PDF services" --secret-string file://client_credentials.json + aws secretsmanager update-secret --secret-id ///client_credentials --description "Updated client credentials for PDF services" --secret-string file://client_credentials.json ``` 6. **Install the Requirements**: - For both Mac and Windows @@ -152,10 +174,10 @@ Ensure your project has the following structure: ``` 10. **Deploy the CDK Stack**: - - Deploy the stack to AWS: - ``` - cdk deploy - ``` + - Deploy the stack to AWS (environment‑aware naming): + - Minimal: `cdk deploy -c env=dev` + - Example prod: `cdk deploy -c env=prod -c stackBase=pdfrem` + - Exact stack name override: `cdk deploy -c stackName=pdfrem-bgdev` ## Usage diff --git a/app.py b/app.py index ab4b36a4..27d95fdd 100644 --- a/app.py +++ b/app.py @@ -18,13 +18,32 @@ ) from constructs import Construct import platform +import os class PDFAccessibility(Stack): def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) - # S3 Bucket - bucket = s3.Bucket(self, "pdfaccessibilitybucket1", encryption=s3.BucketEncryption.S3_MANAGED, enforce_ssl=True) + # Environment context and tags + env_name = (self.node.try_get_context("env") or os.getenv("ENV", "dev")).lower() + stack_base = (self.node.try_get_context("stackBase") or os.getenv("STACK_BASE") or "pdfaccessibility").lower() + name_prefix = f"{stack_base}-{env_name}" + cdk.Tags.of(self).add("Environment", env_name) + cdk.Tags.of(self).add("Project", stack_base) + + # Resolve account and region early for naming + account_id = Stack.of(self).account + region = Stack.of(self).region + + # S3 Bucket (environment-specific name; include account for global uniqueness) + bucket = s3.Bucket( + self, + "pdfaccessibilitybucket1", + encryption=s3.BucketEncryption.S3_MANAGED, + enforce_ssl=True, + # Name: --- + bucket_name=f"{stack_base}-{env_name}-{account_id}-{region}" + ) python_image_asset = ecr_assets.DockerImageAsset(self, "PythonImage", @@ -51,9 +70,16 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: ), ] ) + # Name tag for VPC + cdk.Tags.of(vpc).add("Name", f"{name_prefix}-vpc") # ECS Cluster - cluster = ecs.Cluster(self, "FargateCluster", vpc=vpc) + cluster = ecs.Cluster( + self, + "FargateCluster", + vpc=vpc, + cluster_name=f"{name_prefix}-cluster", + ) ecs_task_execution_role = iam.Role(self, "EcsTaskRole", assumed_by=iam.ServicePrincipal("ecs-tasks.amazonaws.com"), @@ -62,8 +88,6 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: ]) # Allow ECS Task Role to access Bedrock services - account_id = Stack.of(self).account - region = Stack.of(self).region ecs_task_role = iam.Role(self, "EcsTaskExecutionRole", assumed_by=iam.ServicePrincipal("ecs-tasks.amazonaws.com"), @@ -80,20 +104,20 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: actions=["s3:*"], # This gives access to all S3 actions resources=["*"], # This applies the actions to all resources )) - ecs_task_role.add_to_policy(iam.PolicyStatement(actions= - ["secretsmanager:GetSecretValue"], - resources=[f"arn:aws:secretsmanager:{region}:{account_id}:secret:/myapp/db_credentials"] ) - ) + ecs_task_role.add_to_policy(iam.PolicyStatement( + actions=["secretsmanager:GetSecretValue"], + resources=[f"arn:aws:secretsmanager:{region}:{account_id}:secret:/{stack_base}/{env_name}/*"] + )) # Grant S3 read/write access to ECS Task Role bucket.grant_read_write(ecs_task_execution_role) # Create ECS Task Log Groups explicitly python_container_log_group = logs.LogGroup(self, "PythonContainerLogGroup", - log_group_name="/ecs/MyFirstTaskDef/PythonContainerLogGroup", + log_group_name=f"/ecs/{name_prefix}/python", retention=logs.RetentionDays.ONE_WEEK, removal_policy=cdk.RemovalPolicy.DESTROY) javascript_container_log_group = logs.LogGroup(self, "JavaScriptContainerLogGroup", - log_group_name="/ecs/MySecondTaskDef/JavaScriptContainerLogGroup", + log_group_name=f"/ecs/{name_prefix}/javascript", retention=logs.RetentionDays.ONE_WEEK, removal_policy=cdk.RemovalPolicy.DESTROY) # ECS Task Definitions @@ -156,6 +180,14 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: name="model_arn_link", value=model_arn_link ), + tasks.TaskEnvironmentVariable( + name="STACK_BASE", + value=stack_base + ), + tasks.TaskEnvironmentVariable( + name="ENV", + value=env_name + ), ] )], launch_target=tasks.EcsFargateLaunchTarget( @@ -203,6 +235,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: ) java_lambda = lambda_.Function( self, 'JavaLambda', + function_name=f"{name_prefix}-pdf-merger", runtime=lambda_.Runtime.JAVA_21, handler='com.example.App::handleRequest', code=lambda_.Code.from_asset('lambda/java_lambda/PDFMergerLambda/target/PDFMergerLambda-1.0-SNAPSHOT.jar'), @@ -232,6 +265,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: add_title_lambda = lambda_.Function( self, 'AddTitleLambda', + function_name=f"{name_prefix}-add-title", runtime=lambda_.Runtime.PYTHON_3_12, handler='myapp.lambda_handler', code=lambda_.Code.from_docker_build('lambda/add_title'), @@ -265,18 +299,23 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: a11y_precheck = lambda_.Function( self,'accessibility_checker_before_remidiation', + function_name=f"{name_prefix}-a11y-precheck", runtime=lambda_.Runtime.PYTHON_3_10, handler='main.lambda_handler', code=lambda_.Code.from_docker_build('lambda/accessibility_checker_before_remidiation'), timeout=Duration.seconds(900), memory_size=512, architecture=lambda_arch, + environment={ + "STACK_BASE": stack_base, + "ENV": env_name, + } ) a11y_precheck.add_to_role_policy( iam.PolicyStatement( actions=["secretsmanager:GetSecretValue"], - resources=[f"arn:aws:secretsmanager:{region}:{account_id}:secret:/myapp/*"] + resources=[f"arn:aws:secretsmanager:{region}:{account_id}:secret:/{stack_base}/{env_name}/client_credentials*"] )) bucket.grant_read_write(a11y_precheck) a11y_precheck.add_to_role_policy(cloudwatch_logs_policy) @@ -291,18 +330,23 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: a11y_postcheck = lambda_.Function( self,'accessibility_checker_after_remidiation', + function_name=f"{name_prefix}-a11y-postcheck", runtime=lambda_.Runtime.PYTHON_3_10, handler='main.lambda_handler', code=lambda_.Code.from_docker_build('lambda/accessability_checker_after_remidiation'), timeout=Duration.seconds(900), memory_size=512, architecture=lambda_arch, + environment={ + "STACK_BASE": stack_base, + "ENV": env_name, + } ) a11y_postcheck.add_to_role_policy( iam.PolicyStatement( actions=["secretsmanager:GetSecretValue"], - resources=[f"arn:aws:secretsmanager:{region}:{account_id}:secret:/myapp/*"] + resources=[f"arn:aws:secretsmanager:{region}:{account_id}:secret:/{stack_base}/{env_name}/client_credentials*"] )) bucket.grant_read_write(a11y_postcheck) a11y_postcheck.add_to_role_policy(cloudwatch_logs_policy) @@ -323,23 +367,28 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: parallel_state.branch(a11y_precheck_lambda_task) log_group_stepfunctions = logs.LogGroup(self, "StepFunctionLogs", - log_group_name="/aws/states/MyStateMachine_PDFAccessibility", + log_group_name=f"/aws/states/{name_prefix}-state-machine", retention=logs.RetentionDays.ONE_WEEK, removal_policy=cdk.RemovalPolicy.DESTROY ) # State Machine - state_machine = sfn.StateMachine(self, "MyStateMachine", - definition=parallel_state, - timeout=Duration.minutes(150), - logs=sfn.LogOptions( - destination=log_group_stepfunctions, - level=sfn.LogLevel.ALL - )) + state_machine = sfn.StateMachine( + self, + "MyStateMachine", + definition=parallel_state, + timeout=Duration.minutes(150), + logs=sfn.LogOptions( + destination=log_group_stepfunctions, + level=sfn.LogLevel.ALL, + ), + state_machine_name=f"{name_prefix}-state-machine", + ) # Lambda Function split_pdf_lambda = lambda_.Function( self, 'SplitPDF', + function_name=f"{name_prefix}-split-pdf", runtime=lambda_.Runtime.PYTHON_3_10, handler='main.lambda_handler', code=lambda_.Code.from_docker_build("lambda/split_pdf"), @@ -370,10 +419,10 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: java_lambda_log_group_name = f"/aws/lambda/{java_lambda.function_name}" add_title_lambda_log_group_name = f"/aws/lambda/{add_title_lambda.function_name}" accessibility_checker_pre_log_group_name = f"/aws/lambda/{a11y_precheck.function_name}" - accessibility_checker_post_log_group_name = f"aws/lambda/{a11y_postcheck.function_name}" + accessibility_checker_post_log_group_name = f"/aws/lambda/{a11y_postcheck.function_name}" - dashboard = cloudwatch.Dashboard(self, "PDF_Processing_Dashboard", dashboard_name="PDF_Processing_Dashboard", + dashboard = cloudwatch.Dashboard(self, "PDF_Processing_Dashboard", dashboard_name=f"PDF_Processing_Dashboard_{name_prefix}", variables=[cloudwatch.DashboardVariable( id="filename", type=cloudwatch.VariableType.PATTERN, @@ -439,5 +488,24 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: ) app = cdk.App() -PDFAccessibility(app, "PDFAccessibility") + +# Read environment name from context or ENV +env_name = (app.node.try_get_context("env") or os.getenv("ENV", "dev")).lower() + +# Determine account/region from context or CLI-provided defaults (optional) +account = app.node.try_get_context("account") or os.getenv("CDK_DEFAULT_ACCOUNT") +region = app.node.try_get_context("region") or os.getenv("CDK_DEFAULT_REGION") + +# Stack name precedence: stackName > stackBase + env +stack_name_override = app.node.try_get_context("stackName") or os.getenv("STACK_NAME") +stack_base = app.node.try_get_context("stackBase") or os.getenv("STACK_BASE") or "pdfaccessibility" +stack_name = stack_name_override or f"{stack_base}-{env_name}" + +# Allow CDK to infer env if not provided; use explicit env only when both exist +stack_kwargs = {} +if account and region: + stack_kwargs["env"] = cdk.Environment(account=account, region=region) + +PDFAccessibility(app, stack_name, **stack_kwargs) + app.synth() diff --git a/docker_autotag/Dockerfile b/docker_autotag/Dockerfile index 2d919d57..a8b2b099 100644 --- a/docker_autotag/Dockerfile +++ b/docker_autotag/Dockerfile @@ -1,8 +1,7 @@ # Use an official Python runtime as a parent image FROM python:3.10-slim-buster -# Set environment variables -ENV AWS_REGION="us-east-1" +# Region is provided by task execution environment # Set the working directory in the container to /app WORKDIR /app diff --git a/docker_autotag/autotag.py b/docker_autotag/autotag.py index bae8913e..42cc6bec 100644 --- a/docker_autotag/autotag.py +++ b/docker_autotag/autotag.py @@ -128,11 +128,11 @@ def get_secret(basefilename): Returns: tuple: (client_id, client_secret) """ - secret_name = "/myapp/client_credentials" - region_name = "us-east-1" + secret_name = f"/{os.getenv('STACK_BASE','pdfaccessibility')}/{os.getenv('ENV','dev')}/client_credentials" + session = boto3.session.Session() + region_name = session.region_name - session = boto3.session.Session() client = session.client( service_name='secretsmanager', region_name=region_name @@ -658,4 +658,4 @@ def main(): sys.exit(1) if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/javascript_docker/Dockerfile b/javascript_docker/Dockerfile index 9902b97e..19dc425a 100644 --- a/javascript_docker/Dockerfile +++ b/javascript_docker/Dockerfile @@ -17,8 +17,7 @@ COPY package*.json ./ # Install dependencies (force better-sqlite3 to build from source if necessary) RUN npm install -# Set environment variables -ENV AWS_REGION="us-east-1" +# Region is provided by task execution environment # Copy the rest of the application source code COPY . . diff --git a/javascript_docker/alt-text.js b/javascript_docker/alt-text.js index dc5601f7..ad46b324 100644 --- a/javascript_docker/alt-text.js +++ b/javascript_docker/alt-text.js @@ -52,7 +52,7 @@ const logger = winston.createLogger({ }); // Create an S3 client instance. -const s3Client = new S3Client({ region: "us-east-1" }); +const s3Client = new S3Client({ region: process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION }); function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); diff --git a/lambda/accessability_checker_after_remidiation/main.py b/lambda/accessability_checker_after_remidiation/main.py index 43281460..4b51b3a9 100644 --- a/lambda/accessability_checker_after_remidiation/main.py +++ b/lambda/accessability_checker_after_remidiation/main.py @@ -39,7 +39,7 @@ def save_to_s3(bucket_name, file_key): def get_secret(basefilename): - secret_name = "/myapp/client_credentials" + secret_name = f"/{os.getenv('STACK_BASE','pdfaccessibility')}/{os.getenv('ENV','dev')}/client_credentials" session = boto3.session.Session() client = session.client( service_name='secretsmanager' diff --git a/lambda/accessibility_checker_before_remidiation/main.py b/lambda/accessibility_checker_before_remidiation/main.py index b0150d57..55c787fc 100644 --- a/lambda/accessibility_checker_before_remidiation/main.py +++ b/lambda/accessibility_checker_before_remidiation/main.py @@ -35,7 +35,7 @@ def save_to_s3(bucket_name, file_key): def get_secret(basefilename): - secret_name = "/myapp/client_credentials" + secret_name = f"/{os.getenv('STACK_BASE','pdfaccessibility')}/{os.getenv('ENV','dev')}/client_credentials" session = boto3.session.Session() client = session.client( service_name='secretsmanager'