diff --git a/.gitignore b/.gitignore index a45dba0..ee06077 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ coverage.out bin/** *.log .env +src/docs diff --git a/Makefile b/Makefile index cefc973..4c06547 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,4 @@ BINARY_NAME=process-compose -EXT='' RM=rm ifeq ($(OS),Windows_NT) EXT=.exe @@ -10,8 +9,12 @@ endif buildrun: build run +swag: + ~/go/bin/swag init --dir src --output src/docs --parseDependency --parseInternal --parseDepth 1 + build: go build -o bin/${BINARY_NAME}${EXT} ./src + compile: # Linux GOOS=linux GOARCH=386 go build -o bin/${BINARY_NAME}-linux-386 ./src @@ -23,7 +26,7 @@ compile: GOOS=windows GOARCH=amd64 go build -o bin/${BINARY_NAME}-windows-amd64.exe ./src test: - go test -cover ./src + go test -cover ./src/... coverhtml: go test -coverprofile=coverage.out ./src go tool cover -html=coverage.out diff --git a/go.mod b/go.mod index 1682f59..97669fb 100644 --- a/go.mod +++ b/go.mod @@ -4,18 +4,40 @@ go 1.18 require ( github.com/fatih/color v1.13.0 + github.com/gin-gonic/gin v1.7.7 github.com/joho/godotenv v1.4.0 - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b + github.com/swaggo/swag v1.8.1 + gopkg.in/yaml.v2 v2.4.0 ) require ( - github.com/kr/pretty v0.1.0 // indirect - gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect + github.com/KyleBanks/depth v1.2.1 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/go-openapi/spec v0.20.5 // indirect + github.com/go-openapi/swag v0.21.1 // indirect + github.com/go-playground/locales v0.13.0 // indirect + github.com/go-playground/universal-translator v0.17.0 // indirect + github.com/go-playground/validator/v10 v10.4.1 // indirect + github.com/golang/protobuf v1.3.3 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.9 // indirect + github.com/leodido/go-urn v1.2.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect + github.com/ugorji/go/codec v1.1.7 // indirect + golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e // indirect + golang.org/x/net v0.0.0-20220418201149-a630d4f3e7a2 // indirect + golang.org/x/tools v0.1.10 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) require ( github.com/mattn/go-colorable v0.1.9 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/rs/zerolog v1.26.1 - golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect + github.com/swaggo/gin-swagger v1.4.2 + golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect ) diff --git a/go.sum b/go.sum index 7f6c1a0..ba5b3e4 100644 --- a/go.sum +++ b/go.sum @@ -1,32 +1,132 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= +github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/agiledragon/gomonkey/v2 v2.3.1 h1:k+UnUY0EMNYUFUAQVETGY9uUTxjMdnUkP0ARyJS1zzs= +github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +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/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/gzip v0.0.3 h1:etUaeesHhEORpZMp18zoOhepboiWnFtXrBZxszWUn4k= +github.com/gin-contrib/gzip v0.0.3/go.mod h1:YxxswVZIqOvcHEQpsSn+QF5guQtO1dCfy0shBPy4jFc= +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.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= +github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs= +github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= +github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= +github.com/go-openapi/spec v0.20.5 h1:skHa8av4VnAtJU5zyAUXrrdK/NDiVX8lchbG+BfcdrE= +github.com/go-openapi/spec v0.20.5/go.mod h1:QbfOSIVt3/sac+a1wzmKbbcLXm5NdZnyBZYtCijp43o= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU= +github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= +github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE= +github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +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/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc= github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w= +github.com/swaggo/gin-swagger v1.4.2 h1:qDs1YrBOTnurDG/JVMc8678KhoS1B1okQGPtIqVz4YU= +github.com/swaggo/gin-swagger v1.4.2/go.mod h1:hmJ1vPn+XjUvnbzjCdUAxVqgraxELxk8x5zAsjCE5mg= +github.com/swaggo/swag v1.7.9/go.mod h1:gZ+TJ2w/Ve1RwQsA2IRoSOTidHz6DX+PIG8GWvbnoLU= +github.com/swaggo/swag v1.8.1 h1:JuARzFX1Z1njbCGz+ZytBR15TFJwF2Q7fu8puJHhQYI= +github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e h1:1SzTfNOXwIS2oWiMF+6qu0OUDKb0dauo6MoDUQyu+yU= golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220418201149-a630d4f3e7a2 h1:6mzvA99KwZxbOrxww4EvWVQUnN1+xEu9tafK5ZxkYeA= +golang.org/x/net v0.0.0-20220418201149-a630d4f3e7a2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -34,22 +134,41 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/process-compose.yaml b/process-compose.yaml index 1b41c99..b2864cd 100644 --- a/process-compose.yaml +++ b/process-compose.yaml @@ -6,7 +6,6 @@ processes: process1: command: "./test_loop.bash ${PROC4}" - win_command: "powershell.exe ./test_loop.ps1 ${PROC4}" availability: restart: "on-failure" backoff_seconds: 2 @@ -22,7 +21,6 @@ processes: process2: command: "./test_loop.bash process2" - win_command: "powershell.exe ./test_loop.ps1 process2" log_location: ./pc.proc2.log availability: restart: "on-failure" @@ -36,7 +34,6 @@ processes: process3: command: "./test_loop.bash process3" - win_command: "powershell.exe ./test_loop.ps1 process3" availability: restart: "on-failure" backoff_seconds: 2 @@ -46,7 +43,6 @@ processes: process4: command: "./test_loop.bash process4" - win_command: "powershell.exe ./test_loop.ps1 process4" # availability: # restart: on-failure environment: diff --git a/src/api/pc_api.go b/src/api/pc_api.go new file mode 100644 index 0000000..c960e44 --- /dev/null +++ b/src/api/pc_api.go @@ -0,0 +1,27 @@ +package api + +import ( + "net/http" + + "github.com/gin-gonic/gin" + + "github.com/f1bonacc1/process-compose/src/app" +) + +// @Summary Get all processes +// @Produce json +// @Success 200 {object} object "Processes Status" +// @Router /processes [get] +func GetProcesses(c *gin.Context) { + procs, err := app.PROJ.GetLexicographicProcessNames() + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + states := []*app.ProcessState{} + for _, name := range procs { + states = append(states, app.PROJ.GetProcessState(name)) + } + + c.JSON(http.StatusOK, gin.H{"data": states}) +} diff --git a/src/api/routes.go b/src/api/routes.go new file mode 100644 index 0000000..b65e85e --- /dev/null +++ b/src/api/routes.go @@ -0,0 +1,36 @@ +package api + +import ( + _ "github.com/f1bonacc1/process-compose/src/docs" + "github.com/gin-gonic/gin" + ginSwagger "github.com/swaggo/gin-swagger" + "github.com/swaggo/gin-swagger/swaggerFiles" +) + +// @title Process Compose API +// @version 1.0 +// @description process compose description + +// @contact.name API Support +// @contact.url http://www.swagger.io/support +// @contact.email support@swagger.io + +// @license.name Appache 2.0 +// @license.url https://opensource.org/licenses/MIT + +// @host localhost:8080 +// @BasePath / +// @query.collection.format multi + +// InitRouter initialize routing information +func InitRouter() *gin.Engine { + r := gin.New() + r.Use(gin.Logger()) + r.Use(gin.Recovery()) + + url := ginSwagger.URL("http://localhost:8080/swagger/doc.json") // The url pointing to API definition + r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url)) + r.GET("/processes", GetProcesses) + + return r +} diff --git a/src/config.go b/src/app/config.go similarity index 85% rename from src/config.go rename to src/app/config.go index e03bf9f..822c9a8 100644 --- a/src/config.go +++ b/src/app/config.go @@ -1,4 +1,4 @@ -package main +package app import "sync" @@ -10,6 +10,7 @@ type Project struct { Environment []string `yaml:"environment,omitempty"` runningProcesses map[string]*Process + processStates map[string]*ProcessState mapMutex sync.Mutex } @@ -25,6 +26,13 @@ type ProcessConfig struct { Extensions map[string]interface{} `yaml:",inline"` } +type ProcessState struct { + Name string `json:"name"` + Status string `json:"status"` + Restarts int `json:"restarts"` + ExitCode int `json:"exit_code"` +} + func (p ProcessConfig) GetDependencies() []string { dependencies := make([]string, len(p.DependsOn)) @@ -42,6 +50,13 @@ const ( RestartPolicyNo = "no" ) +const ( + ProcessStatePending = "Pending" + ProcessStateRunning = "Running" + ProcessStateRestarting = "Restarting" + ProcessStateCompleted = "Completed" +) + type RestartPolicyConfig struct { Restart string `yaml:",omitempty"` BackoffSeconds int `yaml:"backoff_seconds,omitempty"` diff --git a/src/pc_string.go b/src/app/pc_string.go similarity index 88% rename from src/pc_string.go rename to src/app/pc_string.go index f14c50a..28d486b 100644 --- a/src/pc_string.go +++ b/src/app/pc_string.go @@ -1,4 +1,4 @@ -package main +package app import "strings" diff --git a/src/process.go b/src/app/process.go similarity index 82% rename from src/process.go rename to src/app/process.go index 4e9e72e..208ec3c 100644 --- a/src/process.go +++ b/src/app/process.go @@ -1,4 +1,4 @@ -package main +package app import ( "bufio" @@ -11,26 +11,32 @@ import ( "sync" "time" + "github.com/f1bonacc1/process-compose/src/pclog" + "github.com/fatih/color" "github.com/rs/zerolog/log" ) type Process struct { - globalEnv []string - procConf ProcessConfig - restartsCounter int + globalEnv []string + procConf ProcessConfig + procState *ProcessState sync.Mutex procCond sync.Cond - exitCode int procColor func(a ...interface{}) string noColor func(a ...interface{}) string redColor func(a ...interface{}) string - logger PcLogger + logger pclog.PcLogger done bool replica int } -func NewProcess(globalEnv []string, logger PcLogger, procConf ProcessConfig, replica int) *Process { +func NewProcess( + globalEnv []string, + logger pclog.PcLogger, + procConf ProcessConfig, + procState *ProcessState, + replica int) *Process { colNumeric := rand.Intn(int(color.FgHiWhite)-int(color.FgHiBlack)) + int(color.FgHiBlack) //logger, _ := zap.NewProduction() @@ -41,7 +47,7 @@ func NewProcess(globalEnv []string, logger PcLogger, procConf ProcessConfig, rep redColor: color.New(color.FgHiRed).SprintFunc(), noColor: color.New(color.Reset).SprintFunc(), logger: logger, - exitCode: -1, + procState: procState, done: false, replica: replica, } @@ -58,19 +64,21 @@ func (p *Process) Run() error { go p.handleOutput(stdout, p.handleInfo) go p.handleOutput(stderr, p.handleError) cmd.Start() + p.procState.Status = ProcessStateRunning cmd.Wait() p.Lock() - p.exitCode = cmd.ProcessState.ExitCode() + p.procState.ExitCode = cmd.ProcessState.ExitCode() p.Unlock() - log.Info().Msgf("%s exited with status %d", p.procConf.Name, p.exitCode) + log.Info().Msgf("%s exited with status %d", p.procConf.Name, p.procState.ExitCode) - if !p.isRestartable(p.exitCode) { + if !p.isRestartable(p.procState.ExitCode) { break } - p.restartsCounter += 1 + p.procState.Status = ProcessStateRestarting + p.procState.Restarts += 1 log.Info().Msgf("Restarting %s in %v second(s)... Restarts: %d", - p.procConf.Name, p.getBackoff().Seconds(), p.restartsCounter) + p.procConf.Name, p.getBackoff().Seconds(), p.procState.Restarts) time.Sleep(p.getBackoff()) } @@ -107,14 +115,14 @@ func (p *Process) isRestartable(exitCode int) bool { if p.procConf.RestartPolicy.MaxRestarts == 0 { return true } - return p.restartsCounter < p.procConf.RestartPolicy.MaxRestarts + return p.procState.Restarts < p.procConf.RestartPolicy.MaxRestarts } if p.procConf.RestartPolicy.Restart == RestartPolicyAlways { if p.procConf.RestartPolicy.MaxRestarts == 0 { return true } - return p.restartsCounter < p.procConf.RestartPolicy.MaxRestarts + return p.procState.Restarts < p.procConf.RestartPolicy.MaxRestarts } return false @@ -127,7 +135,7 @@ func (p *Process) WaitForCompletion(waitee string) int { for !p.done { p.procCond.Wait() } - return p.exitCode + return p.procState.ExitCode } func (p *Process) WontRun() { @@ -139,6 +147,7 @@ func (p *Process) onProcessEnd() { if isStringDefined(p.procConf.LogLocation) { p.logger.Close() } + p.procState.Status = ProcessStateCompleted p.Lock() p.done = true p.Unlock() diff --git a/src/project.go b/src/app/project.go similarity index 56% rename from src/project.go rename to src/app/project.go index 4f38474..175013e 100644 --- a/src/project.go +++ b/src/app/project.go @@ -1,13 +1,26 @@ -package main +package app import ( + "errors" "fmt" + "io/ioutil" + "os" + "path/filepath" + "sort" + "strings" "sync" + "github.com/f1bonacc1/process-compose/src/pclog" + "github.com/joho/godotenv" + "github.com/rs/zerolog" "github.com/rs/zerolog/log" + "gopkg.in/yaml.v2" ) +var PROJ *Project + func (p *Project) Run() { + p.initProcessStates() p.runningProcesses = make(map[string]*Process) runOrder := []ProcessConfig{} p.WithServices([]string{}, func(process ProcessConfig) error { @@ -18,9 +31,9 @@ func (p *Project) Run() { for _, v := range runOrder { nameOrder = append(nameOrder, v.Name) } - var logger PcLogger = NewNilLogger("") + var logger pclog.PcLogger = pclog.NewNilLogger("") if isStringDefined(p.LogLocation) { - logger = NewLogger(p.LogLocation) + logger = pclog.NewLogger(p.LogLocation) defer logger.Close() } log.Debug().Msgf("Spinning up %d processes. Order: %q", len(runOrder), nameOrder) @@ -29,9 +42,9 @@ func (p *Project) Run() { procLogger := logger if isStringDefined(proc.LogLocation) { - procLogger = NewLogger(proc.LogLocation) + procLogger = pclog.NewLogger(proc.LogLocation) } - process := NewProcess(p.Environment, procLogger, proc, 1) + process := NewProcess(p.Environment, procLogger, proc, p.GetProcessState(proc.Name), 1) p.addRunningProcess(process) wg.Add(1) go func() { @@ -69,6 +82,29 @@ func (p *Project) WaitIfNeeded(process ProcessConfig) error { return nil } +func (p *Project) initProcessStates() { + p.processStates = make(map[string]*ProcessState) + for key, proc := range p.Processes { + if proc.Disabled { + continue + } + p.processStates[key] = &ProcessState{ + Name: key, + Status: ProcessStatePending, + Restarts: 0, + ExitCode: 0, + } + } +} + +func (p *Project) GetProcessState(name string) *ProcessState { + if procState, ok := p.processStates[name]; ok { + return procState + } + log.Error().Msgf("Error: process %s doesn't exist", name) + return nil +} + func (p *Project) addRunningProcess(process *Process) { p.mapMutex.Lock() p.runningProcesses[process.GetName()] = process @@ -158,3 +194,77 @@ func (p *Project) GetDependenciesOrderNames() ([]string, error) { }) return order, err } + +func (p *Project) GetLexicographicProcessNames() ([]string, error) { + + names := []string{} + for name, proc := range p.Processes { + if proc.Disabled { + continue + } + names = append(names, name) + } + sort.Strings(names) + return names, nil +} + +func CreateProject(inputFile string) *Project { + yamlFile, err := ioutil.ReadFile(inputFile) + + if err != nil { + if errors.Is(err, os.ErrNotExist) { + log.Error().Msgf("File %s doesn't exist", inputFile) + } + log.Fatal().Msg(err.Error()) + } + + // .env is optional we don't care if it errors + godotenv.Load() + + yamlFile = []byte(os.ExpandEnv(string(yamlFile))) + + var project Project + err = yaml.Unmarshal(yamlFile, &project) + if err != nil { + log.Fatal().Msg(err.Error()) + } + if project.LogLevel != "" { + lvl, err := zerolog.ParseLevel(project.LogLevel) + if err != nil { + log.Error().Msgf("Unknown log level %s defaulting to %s", + project.LogLevel, zerolog.GlobalLevel().String()) + } else { + zerolog.SetGlobalLevel(lvl) + } + + } + PROJ = &project + return &project +} + +func findFiles(names []string, pwd string) []string { + candidates := []string{} + for _, n := range names { + f := filepath.Join(pwd, n) + if _, err := os.Stat(f); err == nil { + candidates = append(candidates, f) + } + } + return candidates +} + +// DefaultFileNames defines the Compose file names for auto-discovery (in order of preference) +var DefaultFileNames = []string{"compose.yml", "compose.yaml", "process-compose.yml", "process-compose.yaml"} + +func AutoDiscoverComposeFile(pwd string) (string, error) { + candidates := findFiles(DefaultFileNames, pwd) + if len(candidates) > 0 { + winner := candidates[0] + if len(candidates) > 1 { + log.Warn().Msgf("Found multiple config files with supported names: %s", strings.Join(candidates, ", ")) + log.Warn().Msgf("Using %s", winner) + } + return winner, nil + } + return "", fmt.Errorf("no config files found in %s", pwd) +} diff --git a/src/project_test.go b/src/app/project_test.go similarity index 84% rename from src/project_test.go rename to src/app/project_test.go index f86c1ed..da00bcf 100644 --- a/src/project_test.go +++ b/src/app/project_test.go @@ -1,4 +1,4 @@ -package main +package app import ( "reflect" @@ -7,12 +7,11 @@ import ( func TestProject_GetDependenciesOrderNames(t *testing.T) { type fields struct { - Version string - LogLevel string - LogLocation string - Processes map[string]ProcessConfig - Environment []string - runningProcesses map[string]*Process + Version string + LogLevel string + LogLocation string + Processes map[string]ProcessConfig + Environment []string } tests := []struct { name string @@ -113,11 +112,10 @@ func TestProject_GetDependenciesOrderNames(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { p := &Project{ - Version: tt.fields.Version, - LogLocation: tt.fields.LogLocation, - Processes: tt.fields.Processes, - Environment: tt.fields.Environment, - runningProcesses: tt.fields.runningProcesses, + Version: tt.fields.Version, + LogLocation: tt.fields.LogLocation, + Processes: tt.fields.Processes, + Environment: tt.fields.Environment, } got, err := p.GetDependenciesOrderNames() if (err != nil) != tt.wantErr { diff --git a/src/system_test.go b/src/app/system_test.go similarity index 80% rename from src/system_test.go rename to src/app/system_test.go index 02ae007..e8a395a 100644 --- a/src/system_test.go +++ b/src/app/system_test.go @@ -1,6 +1,7 @@ -package main +package app import ( + "fmt" "os" "path/filepath" "reflect" @@ -9,7 +10,7 @@ import ( ) func getFixtures() []string { - matches, err := filepath.Glob("../fixtures/process-compose-*.yaml") + matches, err := filepath.Glob("../../fixtures/process-compose-*.yaml") if err != nil { panic("no fixtures found") } @@ -26,16 +27,17 @@ func TestSystem_TestFixtures(t *testing.T) { } t.Run(fixture, func(t *testing.T) { - project := createProject(fixture) + project := CreateProject(fixture) project.Run() }) } } func TestSystem_TestComposeWithLog(t *testing.T) { - fixture := filepath.Join("..", "fixtures", "process-compose-with-log.yaml") + fmt.Println(os.Getwd()) + fixture := filepath.Join("..", "..", "fixtures", "process-compose-with-log.yaml") t.Run(fixture, func(t *testing.T) { - project := createProject(fixture) + project := CreateProject(fixture) project.Run() if _, err := os.Stat(project.LogLocation); err != nil { t.Errorf("log file %s not found", project.LogLocation) @@ -55,9 +57,9 @@ func TestSystem_TestComposeWithLog(t *testing.T) { } func TestSystem_TestComposeChain(t *testing.T) { - fixture := filepath.Join("..", "fixtures", "process-compose-chain.yaml") + fixture := filepath.Join("..", "..", "fixtures", "process-compose-chain.yaml") t.Run(fixture, func(t *testing.T) { - project := createProject(fixture) + project := CreateProject(fixture) names, err := project.GetDependenciesOrderNames() if err != nil { t.Errorf("GetDependenciesOrderNames() error = %v", err) @@ -92,7 +94,7 @@ func Test_autoDiscoverComposeFile(t *testing.T) { { name: "Should not find", args: args{ - pwd: "../fixtures", + pwd: "../../fixtures", }, want: "", wantErr: true, @@ -100,15 +102,15 @@ func Test_autoDiscoverComposeFile(t *testing.T) { { name: "Should find process-compose.yaml", args: args{ - pwd: "../", + pwd: "../../", }, - want: filepath.Join("..", "process-compose.yaml"), + want: filepath.Join("..", "..", "process-compose.yaml"), wantErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := autoDiscoverComposeFile(tt.args.pwd) + got, err := AutoDiscoverComposeFile(tt.args.pwd) if (err != nil) != tt.wantErr { t.Errorf("autoDiscoverComposeFile() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/src/main.go b/src/main.go index ac987f5..411d3da 100644 --- a/src/main.go +++ b/src/main.go @@ -1,56 +1,20 @@ package main import ( - "errors" "flag" "fmt" - "io/ioutil" - "path/filepath" - "strings" + "net/http" + "time" - //"log" "os" + "github.com/f1bonacc1/process-compose/src/api" + "github.com/f1bonacc1/process-compose/src/app" + "github.com/gin-gonic/gin" "github.com/rs/zerolog" "github.com/rs/zerolog/log" - - "github.com/joho/godotenv" - "gopkg.in/yaml.v3" ) -func createProject(inputFile string) *Project { - yamlFile, err := ioutil.ReadFile(inputFile) - - if err != nil { - if errors.Is(err, os.ErrNotExist) { - log.Error().Msgf("File %s doesn't exist", inputFile) - } - log.Fatal().Msg(err.Error()) - } - - // .env is optional we don't care if it errors - godotenv.Load() - - yamlFile = []byte(os.ExpandEnv(string(yamlFile))) - - var project Project - err = yaml.Unmarshal(yamlFile, &project) - if err != nil { - log.Fatal().Msg(err.Error()) - } - if project.LogLevel != "" { - lvl, err := zerolog.ParseLevel(project.LogLevel) - if err != nil { - log.Error().Msgf("Unknown log level %s defaulting to %s", - project.LogLevel, zerolog.GlobalLevel().String()) - } else { - zerolog.SetGlobalLevel(lvl) - } - - } - return &project -} - func setupLogger() { log.Logger = log.Output(zerolog.ConsoleWriter{ @@ -60,33 +24,6 @@ func setupLogger() { zerolog.SetGlobalLevel(zerolog.InfoLevel) } -func findFiles(names []string, pwd string) []string { - candidates := []string{} - for _, n := range names { - f := filepath.Join(pwd, n) - if _, err := os.Stat(f); err == nil { - candidates = append(candidates, f) - } - } - return candidates -} - -// DefaultFileNames defines the Compose file names for auto-discovery (in order of preference) -var DefaultFileNames = []string{"compose.yml", "compose.yaml", "process-compose.yml", "process-compose.yaml"} - -func autoDiscoverComposeFile(pwd string) (string, error) { - candidates := findFiles(DefaultFileNames, pwd) - if len(candidates) > 0 { - winner := candidates[0] - if len(candidates) > 1 { - log.Warn().Msgf("Found multiple config files with supported names: %s", strings.Join(candidates, ", ")) - log.Warn().Msgf("Using %s", winner) - } - return winner, nil - } - return "", fmt.Errorf("no config files found in %s", pwd) -} - func isFlagPassed(name string) bool { found := false flag.Visit(func(f *flag.Flag) { @@ -97,22 +34,46 @@ func isFlagPassed(name string) bool { return found } -func main() { +func init() { setupLogger() +} + +func main() { fileName := "" - flag.StringVar(&fileName, "f", DefaultFileNames[0], "path to file to load") + flag.StringVar(&fileName, "f", app.DefaultFileNames[0], "path to file to load") flag.Parse() if !isFlagPassed("f") { pwd, err := os.Getwd() if err != nil { log.Fatal().Msg(err.Error()) } - file, err := autoDiscoverComposeFile(pwd) + file, err := app.AutoDiscoverComposeFile(pwd) if err != nil { log.Fatal().Msg(err.Error()) } fileName = file } - project := createProject(fileName) + + gin.SetMode("") + + routersInit := api.InitRouter() + readTimeout := time.Duration(60) * time.Second + writeTimeout := time.Duration(60) * time.Second + endPoint := fmt.Sprintf(":%d", 8080) + maxHeaderBytes := 1 << 20 + + server := &http.Server{ + Addr: endPoint, + Handler: routersInit, + ReadTimeout: readTimeout, + WriteTimeout: writeTimeout, + MaxHeaderBytes: maxHeaderBytes, + } + + log.Info().Msgf("start http server listening %s", endPoint) + + go server.ListenAndServe() + + project := app.CreateProject(fileName) project.Run() } diff --git a/src/logger_facade.go b/src/pclog/logger_facade.go similarity index 98% rename from src/logger_facade.go rename to src/pclog/logger_facade.go index 4e9f36b..1b292f7 100644 --- a/src/logger_facade.go +++ b/src/pclog/logger_facade.go @@ -1,4 +1,4 @@ -package main +package pclog import ( "bufio" diff --git a/src/logger_interface.go b/src/pclog/logger_interface.go similarity index 90% rename from src/logger_interface.go rename to src/pclog/logger_interface.go index 674568f..05cdc82 100644 --- a/src/logger_interface.go +++ b/src/pclog/logger_interface.go @@ -1,4 +1,4 @@ -package main +package pclog type PcLogger interface { Info(message string, process string, replica int) diff --git a/src/nil_logger.go b/src/pclog/nil_logger.go similarity index 95% rename from src/nil_logger.go rename to src/pclog/nil_logger.go index a83ab90..86d6fb7 100644 --- a/src/nil_logger.go +++ b/src/pclog/nil_logger.go @@ -1,4 +1,4 @@ -package main +package pclog type PcNilLog struct { }