From 69f4248cb4f01deb78a7cacd144cd72d8f731950 Mon Sep 17 00:00:00 2001 From: Lucas Lima Fernandes Date: Mon, 14 Oct 2024 18:26:07 -0300 Subject: [PATCH 1/7] golang-localstack Signed-off-by: Lucas Lima Fernandes --- golang-localstack/README.md | 18 +++ golang-localstack/go.mod | 38 ++++++ golang-localstack/go.sum | 97 ++++++++++++++ .../lambda_examples/lambda_function.py | 7 + .../lambda_function_payload.zip | Bin 0 -> 291 bytes golang-localstack/main.go | 37 ++++++ golang-localstack/services/dyndb.go | 122 +++++++++++++++++ golang-localstack/services/file_upload.go | 124 ++++++++++++++++++ golang-localstack/services/lambda_handler.go | 113 ++++++++++++++++ golang-localstack/testfile.txt | 1 + 10 files changed, 557 insertions(+) create mode 100644 golang-localstack/README.md create mode 100644 golang-localstack/go.mod create mode 100644 golang-localstack/go.sum create mode 100644 golang-localstack/lambda_examples/lambda_function.py create mode 100644 golang-localstack/lambda_examples/lambda_function_payload.zip create mode 100644 golang-localstack/main.go create mode 100644 golang-localstack/services/dyndb.go create mode 100644 golang-localstack/services/file_upload.go create mode 100644 golang-localstack/services/lambda_handler.go create mode 100644 golang-localstack/testfile.txt diff --git a/golang-localstack/README.md b/golang-localstack/README.md new file mode 100644 index 000000000..2e32dc931 --- /dev/null +++ b/golang-localstack/README.md @@ -0,0 +1,18 @@ +# go-localstack + +## awslocal commands + +### Create bucket + +```bash +awslocal --endpoint-url=http://localhost:4566 s3 mb s3://test-bucket +``` + + + + +```bash +awslocal --endpoint-url=http://localhost:4566 s3 ls s3://test-bucket +``` + + diff --git a/golang-localstack/go.mod b/golang-localstack/go.mod new file mode 100644 index 000000000..5dbfc42c7 --- /dev/null +++ b/golang-localstack/go.mod @@ -0,0 +1,38 @@ +module github.com/lucaslimafernandes/go-localstack + +go 1.22.5 + +require ( + github.com/aws/aws-sdk-go v1.55.5 + github.com/gin-gonic/gin v1.10.0 +) + +require ( + github.com/bytedance/sonic v1.11.6 // indirect + github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.20.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect + golang.org/x/arch v0.8.0 // indirect + golang.org/x/crypto v0.23.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/golang-localstack/go.sum b/golang-localstack/go.sum new file mode 100644 index 000000000..ce2cb46e9 --- /dev/null +++ b/golang-localstack/go.sum @@ -0,0 +1,97 @@ +github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= +github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= +github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= +github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= +github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= +github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= +github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= +golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/golang-localstack/lambda_examples/lambda_function.py b/golang-localstack/lambda_examples/lambda_function.py new file mode 100644 index 000000000..aa3a2ee9c --- /dev/null +++ b/golang-localstack/lambda_examples/lambda_function.py @@ -0,0 +1,7 @@ +# lambda_function.py + +def lambda_handler(event, context): + return { + 'statusCode': 200, + 'body': 'ping pong' + } diff --git a/golang-localstack/lambda_examples/lambda_function_payload.zip b/golang-localstack/lambda_examples/lambda_function_payload.zip new file mode 100644 index 0000000000000000000000000000000000000000..bdee00649d64a52e2116b8e0aee0db48762d3298 GIT binary patch literal 291 zcmWIWW@Zs#U|`^2Sh&JFk|n#}ITOfh0b(Hr8HSw1+@zGm__WfzY`LB2H&YD)K*uvMFaq(GMi2{|Cs-k# WK=VL=H!B-R2O|(h0O_qD4g&ydK3(?! literal 0 HcmV?d00001 diff --git a/golang-localstack/main.go b/golang-localstack/main.go new file mode 100644 index 000000000..ac0452b75 --- /dev/null +++ b/golang-localstack/main.go @@ -0,0 +1,37 @@ +package main + +import ( + "net/http" + + "github.com/gin-gonic/gin" + "github.com/lucaslimafernandes/go-localstack/services" +) + +func main() { + + router := gin.Default() + // gin.SetMode(gin.ReleaseMode) + + router.GET("/", hello) + + // s3 routes + router.GET("/s3/create-bucket", services.CreateBucket) + router.GET("/s3/upload", services.FileUpload) + router.GET("/s3/ls", services.ListBucket) + + // DynamoDB routes + router.GET("/dynamodb/create-table", services.CreateDynamoTable) + router.GET("/dynamodb/insert", services.InsertItemDynamo) + router.GET("/dynamodb/list", services.ListItemsDynamo) + + // Lambda Functions + router.GET("/lambda/create-function", services.CreateLambda) + router.GET("/lambda/invoke", services.InvokeLambda) + router.GET("/lambda/ls", services.ListLambdas) + + router.Run(":8080") +} + +func hello(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{"ok": "Hello, World!"}) +} diff --git a/golang-localstack/services/dyndb.go b/golang-localstack/services/dyndb.go new file mode 100644 index 000000000..c8e0339d5 --- /dev/null +++ b/golang-localstack/services/dyndb.go @@ -0,0 +1,122 @@ +package services + +import ( + "net/http" + "os" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/dynamodb" + "github.com/gin-gonic/gin" +) + +func CreateDynamoTable(c *gin.Context) { + + sess, err := session.NewSession(&aws.Config{ + Region: aws.String(os.Getenv("S3_REGION")), + Endpoint: aws.String(os.Getenv("S3_ENDPOINT")), + Credentials: credentials.NewStaticCredentials(os.Getenv("S3_ACCESS_KEY_ID"), os.Getenv("S3_ACCESS_KEY"), ""), + S3ForcePathStyle: aws.Bool(true), // Enable path-style + }) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + svc := dynamodb.New(sess) + + tableName := "users" + + input := &dynamodb.CreateTableInput{ + TableName: &tableName, + KeySchema: []*dynamodb.KeySchemaElement{ + { + AttributeName: aws.String("ID"), + KeyType: aws.String("HASH"), + }, + }, + AttributeDefinitions: []*dynamodb.AttributeDefinition{ + { + AttributeName: aws.String("ID"), + AttributeType: aws.String("S"), + }, + }, + BillingMode: aws.String("PAY_PER_REQUEST"), + } + + _, err = svc.CreateTable(input) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{"message": "DynamoDB table created successfully"}) + +} + +func InsertItemDynamo(c *gin.Context) { + + sess, err := session.NewSession(&aws.Config{ + Region: aws.String(os.Getenv("S3_REGION")), + Endpoint: aws.String(os.Getenv("S3_ENDPOINT")), + Credentials: credentials.NewStaticCredentials(os.Getenv("S3_ACCESS_KEY_ID"), os.Getenv("S3_ACCESS_KEY"), ""), + S3ForcePathStyle: aws.Bool(true), // Enable path-style + }) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + svc := dynamodb.New(sess) + + input := &dynamodb.PutItemInput{ + TableName: aws.String("users"), + Item: map[string]*dynamodb.AttributeValue{ + "ID": { + S: aws.String("123"), + }, + "Name": { + S: aws.String("Lucas"), + }, + }, + } + + _, err = svc.PutItem(input) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{"message": "Item inserted successfully!"}) + +} + +func ListItemsDynamo(c *gin.Context) { + + sess, err := session.NewSession(&aws.Config{ + Region: aws.String(os.Getenv("S3_REGION")), + Endpoint: aws.String(os.Getenv("S3_ENDPOINT")), + Credentials: credentials.NewStaticCredentials(os.Getenv("S3_ACCESS_KEY_ID"), os.Getenv("S3_ACCESS_KEY"), ""), + S3ForcePathStyle: aws.Bool(true), // Enable path-style + }) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + svc := dynamodb.New(sess) + + scan := &dynamodb.ScanInput{ + TableName: aws.String("users"), + } + + result, err := svc.Scan(scan) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{"items": result.Items}) + +} diff --git a/golang-localstack/services/file_upload.go b/golang-localstack/services/file_upload.go new file mode 100644 index 000000000..95012d373 --- /dev/null +++ b/golang-localstack/services/file_upload.go @@ -0,0 +1,124 @@ +package services + +import ( + "bytes" + "io" + "net/http" + "os" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/s3" + "github.com/gin-gonic/gin" +) + +func FileUpload(c *gin.Context) { + + var uploadBody io.ReadSeeker + + src, err := os.Open("testfile.txt") + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Unable to read the file"}) + return + } + defer src.Close() + + filename := aws.String("testfile.txt") + + fileContent, err := io.ReadAll(src) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + // fmt.Println(string(fileContent)) + + uploadBody = bytes.NewReader(fileContent) + + sess, err := session.NewSession(&aws.Config{ + Region: aws.String(os.Getenv("S3_REGION")), + Endpoint: aws.String(os.Getenv("S3_ENDPOINT")), + Credentials: credentials.NewStaticCredentials(os.Getenv("S3_ACCESS_KEY_ID"), os.Getenv("S3_ACCESS_KEY"), ""), + S3ForcePathStyle: aws.Bool(true), // Enable path-style + }) + + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + // Cria um novo cliente do S3 + svc := s3.New(sess) + + uploadParams := &s3.PutObjectInput{ + Bucket: aws.String(os.Getenv("S3_BUCKET")), + Key: filename, + Body: uploadBody, + } + + _, err = svc.PutObject(uploadParams) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"err": err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{"data": "OK"}) + +} + +func CreateBucket(c *gin.Context) { + + sess, err := session.NewSession(&aws.Config{ + Region: aws.String(os.Getenv("S3_REGION")), + Endpoint: aws.String(os.Getenv("S3_ENDPOINT")), + Credentials: credentials.NewStaticCredentials(os.Getenv("S3_ACCESS_KEY_ID"), os.Getenv("S3_ACCESS_KEY"), ""), + S3ForcePathStyle: aws.Bool(true), // Enable path-style + }) + if err != nil { + c.JSON((http.StatusInternalServerError), gin.H{"error": err.Error()}) + return + } + + svc := s3.New(sess) + + bucketName := "test-bucket" + + createBucketInput := &s3.CreateBucketInput{ + Bucket: &bucketName, + } + + _, err = svc.CreateBucket(createBucketInput) + if err != nil { + c.JSON((http.StatusInternalServerError), gin.H{"error": err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{"data": "OK"}) + +} + +func ListBucket(c *gin.Context) { + + sess, err := session.NewSession(&aws.Config{ + Region: aws.String(os.Getenv("S3_REGION")), + Endpoint: aws.String(os.Getenv("S3_ENDPOINT")), + Credentials: credentials.NewStaticCredentials(os.Getenv("S3_ACCESS_KEY_ID"), os.Getenv("S3_ACCESS_KEY"), ""), + S3ForcePathStyle: aws.Bool(true), // Enable path-style + }) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + svc := s3.New(sess) + + res, err := svc.ListObjects(&s3.ListObjectsInput{Bucket: aws.String("test-bucket")}) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{"response": res.Contents}) + +} diff --git a/golang-localstack/services/lambda_handler.go b/golang-localstack/services/lambda_handler.go new file mode 100644 index 000000000..419dc5e17 --- /dev/null +++ b/golang-localstack/services/lambda_handler.go @@ -0,0 +1,113 @@ +package services + +import ( + "encoding/json" + "net/http" + "os" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/lambda" + "github.com/gin-gonic/gin" +) + +func CreateLambda(c *gin.Context) { + + sess, err := session.NewSession(&aws.Config{ + Region: aws.String(os.Getenv("S3_REGION")), + Endpoint: aws.String(os.Getenv("S3_ENDPOINT")), + Credentials: credentials.NewStaticCredentials(os.Getenv("S3_ACCESS_KEY_ID"), os.Getenv("S3_ACCESS_KEY"), ""), + S3ForcePathStyle: aws.Bool(true), // Enable path-style + }) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + zipFile, err := os.ReadFile("lambda_examples/lambda_function_payload.zip") + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "unable to read zip file"}) + return + } + + svc := lambda.New(sess) + + input := &lambda.CreateFunctionInput{ + Code: &lambda.FunctionCode{ + ZipFile: zipFile, + }, + FunctionName: aws.String("Example"), + Handler: aws.String("lambda_function.lambda_handler"), + Role: aws.String("arn:aws:iam::000000000000:role/lambda-role"), + Runtime: aws.String("python3.8"), + Timeout: aws.Int64(20), + } + + result, err := svc.CreateFunction(input) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{"response": result}) + +} + +func ListLambdas(c *gin.Context) { + + sess, err := session.NewSession(&aws.Config{ + Region: aws.String(os.Getenv("S3_REGION")), + Endpoint: aws.String(os.Getenv("S3_ENDPOINT")), + Credentials: credentials.NewStaticCredentials(os.Getenv("S3_ACCESS_KEY_ID"), os.Getenv("S3_ACCESS_KEY"), ""), + S3ForcePathStyle: aws.Bool(true), // Enable path-style + }) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + svc := lambda.New(sess) + + result, err := svc.ListFunctions(&lambda.ListFunctionsInput{}) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{"functions": result.Functions}) +} + +func InvokeLambda(c *gin.Context) { + + sess, err := session.NewSession(&aws.Config{ + Region: aws.String(os.Getenv("S3_REGION")), + Endpoint: aws.String(os.Getenv("S3_ENDPOINT")), + Credentials: credentials.NewStaticCredentials(os.Getenv("S3_ACCESS_KEY_ID"), os.Getenv("S3_ACCESS_KEY"), ""), + S3ForcePathStyle: aws.Bool(true), // Enable path-style + }) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + svc := lambda.New(sess) + + payload, _ := json.Marshal(map[string]interface{}{ + "key": "value", + }) + + input := &lambda.InvokeInput{ + FunctionName: aws.String("Example"), + Payload: payload, + } + + result, err := svc.Invoke(input) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{"response": string(result.Payload)}) + +} diff --git a/golang-localstack/testfile.txt b/golang-localstack/testfile.txt new file mode 100644 index 000000000..fabe59a2b --- /dev/null +++ b/golang-localstack/testfile.txt @@ -0,0 +1 @@ +testfile.txt From 79a1b68a0d3ef5a38a854f7ff1b3bc9dce2da0a1 Mon Sep 17 00:00:00 2001 From: Lucas Lima Fernandes Date: Mon, 14 Oct 2024 19:44:30 -0300 Subject: [PATCH 2/7] Alter function response, alter readme Signed-off-by: Lucas Lima Fernandes --- .../lambda_examples/lambda_function.py | 2 +- .../lambda_examples/lambda_function_payload.zip | Bin 291 -> 287 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/golang-localstack/lambda_examples/lambda_function.py b/golang-localstack/lambda_examples/lambda_function.py index aa3a2ee9c..99878a10a 100644 --- a/golang-localstack/lambda_examples/lambda_function.py +++ b/golang-localstack/lambda_examples/lambda_function.py @@ -3,5 +3,5 @@ def lambda_handler(event, context): return { 'statusCode': 200, - 'body': 'ping pong' + 'body': 'ok' } diff --git a/golang-localstack/lambda_examples/lambda_function_payload.zip b/golang-localstack/lambda_examples/lambda_function_payload.zip index bdee00649d64a52e2116b8e0aee0db48762d3298..684e8d54e07bf9709ad0827a0db093920b3e8ada 100644 GIT binary patch delta 199 zcmZ3?G@nU4z?+#xgn@y9gW=sAzev-XOsP~LuXduiT>XN%yy+lZTEWf0$nt`jfdNbe zhn?^|D%0yuJUZ@lOD5uyPSvGH&;8U~`6`Udjg8HUW95=RQ@j=|sH)p$6|rF& fH$#9oqZpGMGd7o<(_sd>YT{o7wv9lSGB5xD?{7!Q delta 203 zcmbQww3taez?+#xgn@y9gJIzc??{&He&1bbvEUz4#)TpGLi)B#_G-o}SDPYFGvLK-W$Dslc`s=voE_0O3_mK>z>% From cf2220ee7d40da6e0b4a66b5b2d2c5bd71f9854d Mon Sep 17 00:00:00 2001 From: Lucas Lima Fernandes Date: Mon, 14 Oct 2024 19:44:38 -0300 Subject: [PATCH 3/7] Alter function response, alter readme Signed-off-by: Lucas Lima Fernandes --- golang-localstack/README.md | 155 ++++++++++++++++++++++++++++++++++-- 1 file changed, 149 insertions(+), 6 deletions(-) diff --git a/golang-localstack/README.md b/golang-localstack/README.md index 2e32dc931..34f693546 100644 --- a/golang-localstack/README.md +++ b/golang-localstack/README.md @@ -1,18 +1,161 @@ -# go-localstack +# Compose Sample Application -## awslocal commands +## Golang Application with AWS Simulation using LocalStack -### Create bucket +This project simulates AWS services such as S3, DynamoDB, and Lambda using LocalStack, and a Golang API for interaction with these services. -```bash -awslocal --endpoint-url=http://localhost:4566 s3 mb s3://test-bucket +### Project Structure: + +```plaintext +. +├── go.mod # Go module definitions +├── go.sum # Go module dependencies +├── lambda_examples # Directory containing Lambda examples +│ ├── lambda_function_payload.zip # Zipped Python Lambda function +│ └── lambda_function.py # Python Lambda function source code +├── main.go # Main entry point for the Go API +├── README.md # Project README file +├── services # Go services for interacting with AWS services +│ ├── dyndb.go # DynamoDB service implementation +│ ├── file_upload.go # S3 file upload service +│ └── lambda_handler.go # Lambda invocation service +└── testfile.txt # Test file for upload ``` +### _compose.yaml_ + +This is a sample `docker-compose` file for running LocalStack and the Golang application. + +```yaml +services: + + localstack: + image: localstack/localstack:latest + environment: + - SERVICES=lambda,s3,dynamodb + - DEBUG=1 + ports: + - "4566:4566" # LocalStack service endpoint + - "4571:4571" # Optional additional port + volumes: + - ./localstack:/docker-entrypoint-initaws.d + - /var/run/docker.sock:/var/run/docker.sock # Docker socket for Lambda runtime execution + container_name: localstack + + app: + build: + context: . + dockerfile: Dockerfile + depends_on: + - localstack + environment: + - S3_REGION=us-east-1 + - S3_ENDPOINT=http://localstack:4566 + - S3_ACCESS_KEY_ID=test + - S3_ACCESS_KEY=test + - S3_BUCKET=test-bucket + ports: + - "8080:8080" # Exposing API service on port 8080 + container_name: golang_app +``` + +### Running the Application with Docker Compose + +You can deploy the application using Docker Compose, which will start both the LocalStack (simulating AWS services) and the Golang application. + +#### Steps: + +1. **Build and start the containers**: + + ```bash + docker compose up -d + ``` + + This command will create the network, build the images, and start the services for LocalStack and the Golang app. + + Example output: + + ```bash + Creating network "go_localstack_default" with the default driver + Building app + Step 1/6 : FROM golang:1.19-alpine + ... + Creating localstack ... done + Creating golang_app ... done + ``` + +2. **Verify the containers are running**: + + ```bash + docker ps + ``` + + Example output: + ```bash + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES + 3adaea94142d golang_app "go run main.go" 1 minute ago Up 1 minute 0.0.0.0:8080->8080/tcp golang_app + 9d8acb32cd4e localstack/localstack "docker-entrypoint.sh…" 1 minute ago Up 1 minute 0.0.0.0:4566->4566/tcp localstack + ``` +3. **Access the application**: + + After the application starts, navigate to `http://localhost:8080` to interact with the Golang API. + +4. **API Routes**: + + The Golang application exposes several routes for interacting with LocalStack services: + + - **S3 Routes**: + - `GET /s3/create-bucket`: Creates an S3 bucket in LocalStack. + - `GET /s3/upload`: Uploads the file `testfile.txt` to the S3 bucket. + - `GET /s3/ls`: Lists the contents of the S3 bucket. + + - **DynamoDB Routes**: + - `GET /dynamodb/create-table`: Creates a DynamoDB table in LocalStack. + - `GET /dynamodb/insert`: Inserts a record into the DynamoDB table. + - `GET /dynamodb/list`: Lists the records in the DynamoDB table. + + - **Lambda Routes**: + - `GET /lambda/create-function`: Creates a Lambda function from the `lambda_function_payload.zip` file. + - `GET /lambda/invoke`: Invokes the Lambda function. + - `GET /lambda/ls`: Lists the Lambda functions available. + + - **General Route**: + - `GET /`: Simple "Hello, World!" response. + +### Expected Results + +1. **Lambda Invocation**: + When a Lambda function is invoked, it should return a `200` status code with a response like: + + ```json + { + "statusCode": 200, + "body": "ping pong" + } + ``` + +2. **File Upload**: + The `testfile.txt` should be uploaded to the S3 bucket, and you can verify its presence by listing the contents of the bucket. + +3. **DynamoDB Operations**: + You can create a DynamoDB table, insert records, and list them using the provided routes. + +### Stopping and Removing the Containers + +To stop and remove the containers, run: ```bash -awslocal --endpoint-url=http://localhost:4566 s3 ls s3://test-bucket +docker compose down ``` +This command will stop all running containers and remove them along with the associated network. + +--- + +### Additional Information + +- The project simulates AWS services using **LocalStack**. You can interact with S3, DynamoDB, and Lambda by sending HTTP requests to the Go application, which acts as an API wrapper for these AWS services. +- Ensure that Docker is correctly installed and that the `/var/run/docker.sock` is mounted to allow Lambda functions to run within the LocalStack environment. From 08df4a28ce2c105c85626c56fbdf9dd6fb3a90f7 Mon Sep 17 00:00:00 2001 From: Lucas Lima Fernandes Date: Tue, 15 Oct 2024 17:06:55 -0300 Subject: [PATCH 4/7] Golang+Localstack s3,dynamodb,lambda Signed-off-by: Lucas Lima Fernandes --- golang-localstack/README.md | 144 ++++++++++++++++++++++++++++++------ 1 file changed, 122 insertions(+), 22 deletions(-) diff --git a/golang-localstack/README.md b/golang-localstack/README.md index 34f693546..3876802c9 100644 --- a/golang-localstack/README.md +++ b/golang-localstack/README.md @@ -2,7 +2,7 @@ ## Golang Application with AWS Simulation using LocalStack -This project simulates AWS services such as S3, DynamoDB, and Lambda using LocalStack, and a Golang API for interaction with these services. +This project simulates AWS services such as S3, DynamoDB, and Lambda using LocalStack, and provides a Golang API for interaction with these services. ### Project Structure: @@ -68,7 +68,7 @@ You can deploy the application using Docker Compose, which will start both the L 1. **Build and start the containers**: ```bash - docker compose up -d + docker compose up -d --build ``` This command will create the network, build the images, and start the services for LocalStack and the Golang app. @@ -76,12 +76,11 @@ You can deploy the application using Docker Compose, which will start both the L Example output: ```bash - Creating network "go_localstack_default" with the default driver - Building app - Step 1/6 : FROM golang:1.19-alpine + [+] Building 1.0s (16/16) FINISHED ... - Creating localstack ... done - Creating golang_app ... done + [+] Running 2/2 + ✔ Container localstack Running 0.0s + ✔ Container golang_app Started 0.3s ``` 2. **Verify the containers are running**: @@ -93,9 +92,9 @@ You can deploy the application using Docker Compose, which will start both the L Example output: ```bash - CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES - 3adaea94142d golang_app "go run main.go" 1 minute ago Up 1 minute 0.0.0.0:8080->8080/tcp golang_app - 9d8acb32cd4e localstack/localstack "docker-entrypoint.sh…" 1 minute ago Up 1 minute 0.0.0.0:4566->4566/tcp localstack + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES + e97c72533b0e go-localstack-app "./main" 3 days ago Up About a minute 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp golang_app + eef6573ca52c localstack/localstack:latest "docker-entrypoint.sh" 3 days ago Up 4 minutes (healthy) 0.0.0.0:4566->4566/tcp, :::4566->4566/tcp, 4510-4559/tcp, 5678/tcp, 0.0.0.0:4571->4571/tcp, :::4571->4571/tcp localstack ``` 3. **Access the application**: @@ -106,6 +105,9 @@ You can deploy the application using Docker Compose, which will start both the L The Golang application exposes several routes for interacting with LocalStack services: + - **General Route**: + - `GET /`: Simple "Hello, World!" response. + - **S3 Routes**: - `GET /s3/create-bucket`: Creates an S3 bucket in LocalStack. - `GET /s3/upload`: Uploads the file `testfile.txt` to the S3 bucket. @@ -119,29 +121,127 @@ You can deploy the application using Docker Compose, which will start both the L - **Lambda Routes**: - `GET /lambda/create-function`: Creates a Lambda function from the `lambda_function_payload.zip` file. - `GET /lambda/invoke`: Invokes the Lambda function. - - `GET /lambda/ls`: Lists the Lambda functions available. - - - **General Route**: - - `GET /`: Simple "Hello, World!" response. + - `GET /lambda/ls`: Lists the available Lambda functions. ### Expected Results -1. **Lambda Invocation**: - When a Lambda function is invoked, it should return a `200` status code with a response like: - +1. **General Route** + When you access the general route, it should return a simple response: ```json { - "statusCode": 200, - "body": "ping pong" + "ok": "Hello, World!" } ``` -2. **File Upload**: +2. **S3 Routes** The `testfile.txt` should be uploaded to the S3 bucket, and you can verify its presence by listing the contents of the bucket. -3. **DynamoDB Operations**: + - Creating the bucket: + + ```json + { + "data": "OK" + } + ``` + + - Uploading the example file: + + ```json + { + "data": "OK" + } + ``` + + - Listing all existing files: + + ```json + { + "response": [ + { + "Key": "testfile.txt", + "LastModified": "2024-10-15T00:11:40Z", + "Size": 314, + "StorageClass": "STANDARD" + } + ] + } + ``` + +3. **DynamoDB Operations** You can create a DynamoDB table, insert records, and list them using the provided routes. + - Creating the DynamoDB table: + + ```json + { + "message": "DynamoDB table created successfully" + } + ``` + + - Inserting data: + + ```json + { + "message": "Item inserted successfully!" + } + ``` + + - Listing the records: + + ```json + { + "items": [ + { + "ID": { + "S": "123" + }, + "Name": { + "S": "Lucas" + } + } + ] + } + ``` + +4. **Lambda Invocation**: + When a Lambda function is invoked, it should return a `200` status code with a response like: + + - Creating a Lambda function: + + ```json + { + "response": { + "FunctionName": "Example", + "Handler": "lambda_function.lambda_handler", + "Runtime": "python3.8", + "State": "Pending" + } + } + ``` + + - Listing functions: + + ```json + { + "functions": [ + { + "FunctionName": "Example", + "Handler": "lambda_function.lambda_handler", + "Runtime": "python3.8" + } + ] + } + ``` + + - Invoking the function: + + ```json + { + "statusCode": 200, + "body": "ok" + } + ``` + ### Stopping and Removing the Containers To stop and remove the containers, run: @@ -156,6 +256,6 @@ This command will stop all running containers and remove them along with the ass ### Additional Information -- The project simulates AWS services using **LocalStack**. You can interact with S3, DynamoDB, and Lambda by sending HTTP requests to the Go application, which acts as an API wrapper for these AWS services. +- This project simulates AWS services using **LocalStack**. You can interact with S3, DynamoDB, and Lambda by sending HTTP requests to the Golang application, which acts as an API wrapper for these AWS services. - Ensure that Docker is correctly installed and that the `/var/run/docker.sock` is mounted to allow Lambda functions to run within the LocalStack environment. From 9d91cec4309bc56497cca3b632e7de6a1088d982 Mon Sep 17 00:00:00 2001 From: Lucas Lima Fernandes Date: Tue, 15 Oct 2024 18:27:09 -0300 Subject: [PATCH 5/7] Add Dockerfile Signed-off-by: Lucas Lima Fernandes --- golang-localstack/Dockerfile | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 golang-localstack/Dockerfile diff --git a/golang-localstack/Dockerfile b/golang-localstack/Dockerfile new file mode 100644 index 000000000..763c75fa0 --- /dev/null +++ b/golang-localstack/Dockerfile @@ -0,0 +1,22 @@ + +FROM golang:1.22-alpine AS builder + +WORKDIR /app + +COPY . . + +RUN go build -o main . + +FROM alpine:3.19 + +WORKDIR /app + +COPY --from=builder /app/main . + +# Copy the file directly in the container +COPY testfile.txt /app/testfile.txt +COPY lambda_examples/lambda_function_payload.zip /app/lambda_examples/lambda_function_payload.zip + +# EXPOSE 8080 + +CMD ["./main"] From 77d6019dbcd8902a066b04d3da785776c19548c2 Mon Sep 17 00:00:00 2001 From: Lucas Lima Fernandes Date: Tue, 15 Oct 2024 18:30:20 -0300 Subject: [PATCH 6/7] Update project structure in readme file Signed-off-by: Lucas Lima Fernandes --- golang-localstack/README.md | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/golang-localstack/README.md b/golang-localstack/README.md index 3876802c9..e68c06805 100644 --- a/golang-localstack/README.md +++ b/golang-localstack/README.md @@ -8,18 +8,22 @@ This project simulates AWS services such as S3, DynamoDB, and Lambda using Local ```plaintext . -├── go.mod # Go module definitions -├── go.sum # Go module dependencies -├── lambda_examples # Directory containing Lambda examples -│ ├── lambda_function_payload.zip # Zipped Python Lambda function -│ └── lambda_function.py # Python Lambda function source code -├── main.go # Main entry point for the Go API -├── README.md # Project README file -├── services # Go services for interacting with AWS services -│ ├── dyndb.go # DynamoDB service implementation -│ ├── file_upload.go # S3 file upload service -│ └── lambda_handler.go # Lambda invocation service -└── testfile.txt # Test file for upload +├── docker-compose.yaml # Docker Compose file to start LocalStack and the Golang app +├── Dockerfile # Dockerfile for building the Golang app container +├── go.mod # Go module definitions +├── go.sum # Go module dependencies +├── lambda_examples # Directory containing Lambda examples +│ ├── lambda_function_payload.zip # Zipped Python Lambda function +│ └── lambda_function.py # Python Lambda function source code +├── main.go # Main entry point for the Go API +├── README.md # Project README file +├── services # Go services for interacting with AWS services +│ ├── dyndb.go # DynamoDB service implementation +│ ├── file_upload.go # S3 file upload service +│ └── lambda_handler.go # Lambda invocation service +└── testfile.txt # Test file for upload + +2 directories, 12 files ``` ### _compose.yaml_ From c0bbc93e4f63ec8e016f383c84ff3bfdd750edd0 Mon Sep 17 00:00:00 2001 From: Lucas Lima Fernandes Date: Tue, 15 Oct 2024 18:32:31 -0300 Subject: [PATCH 7/7] Add docker compose file Signed-off-by: Lucas Lima Fernandes --- golang-localstack/docker-compose.yaml | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 golang-localstack/docker-compose.yaml diff --git a/golang-localstack/docker-compose.yaml b/golang-localstack/docker-compose.yaml new file mode 100644 index 000000000..fda43af8e --- /dev/null +++ b/golang-localstack/docker-compose.yaml @@ -0,0 +1,31 @@ +services: + + localstack: + image: localstack/localstack:latest + environment: + - SERVICES=s3,dynamodb,lambda + - DEBUG=1 + ports: + - "4566:4566" # LocalStack service endpoint + - "4571:4571" # Optional additional port + volumes: + - ./localstack:/docker-entrypoint-initaws.d + - /var/run/docker.sock:/var/run/docker.sock # Docker socket for Lambda runtime execution + container_name: localstack + + + app: + build: + context: . + dockerfile: Dockerfile + depends_on: + - localstack + environment: + - S3_REGION=us-east-1 + - S3_ENDPOINT=http://localstack:4566 + - S3_ACCESS_KEY_ID=test + - S3_ACCESS_KEY=test + - S3_BUCKET=test-bucket + ports: + - "8080:8080" + container_name: golang_app