From 270d2cb5b1f8955eee02f1612179297dac6932a8 Mon Sep 17 00:00:00 2001 From: Thomas Bellembois Date: Mon, 5 Sep 2022 15:59:31 +0200 Subject: [PATCH] First commit. --- .gitignore | 24 ++++ .golangci.yml | 102 ++++++++++++++++ factory.go | 216 +++++++++++++++++++++++++++++++++ go.mod | 20 +++ go.sum | 116 ++++++++++++++++++ iclient/iclient.go | 35 ++++++ messagesender/messagesender.go | 128 +++++++++++++++++++ 7 files changed, 641 insertions(+) create mode 100644 .gitignore create mode 100644 .golangci.yml create mode 100644 factory.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 iclient/iclient.go create mode 100644 messagesender/messagesender.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b9abd17 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# ---> Go +# If you prefer the allow list template instead of the deny list, see community template: +# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore +# +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Go workspace file +go.work + +settings.json \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..7a982dc --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,102 @@ +# options for analysis running +run: + # timeout for analysis, e.g. 30s, 5m, default is 1m + timeout: 1m + + # exit code when at least one issue was found, default is 1 + issues-exit-code: 0 + + # include test files or not, default is true + tests: false + + # which dirs to skip: issues from them won't be reported; + # can use regexp here: generated.*, regexp is applied on full path; + # default value is empty list, but default dirs are skipped independently + # from this option's value (see skip-dirs-use-default). + # "/" will be replaced by current OS file path separator to properly work + # on Windows. + skip-dirs: + - wasm + - static + - node_modules + - documents + - docker + - bind-* + + # default is true. Enables skipping of directories: + # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ + skip-dirs-use-default: true + + # by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules": + # If invoked with -mod=readonly, the go command is disallowed from the implicit + # automatic updating of go.mod described above. Instead, it fails when any changes + # to go.mod are needed. This setting is most useful to check that go.mod does + # not need updates, such as in a continuous integration and testing system. + # If invoked with -mod=vendor, the go command assumes that the vendor + # directory holds the correct copies of dependencies and ignores + # the dependency descriptions in go.mod. + modules-download-mode: mod + + # Allow multiple parallel golangci-lint instances running. + # If false (default) - golangci-lint acquires file lock on start. + allow-parallel-runners: true + + +# output configuration options +output: + # colored-line-number|line-number|json|tab|checkstyle|code-climate|junit-xml|github-actions + # default is "colored-line-number" + format: colored-line-number + + # print lines of code with issue, default is true + print-issued-lines: true + + # print linter name in the end of issue text, default is true + print-linter-name: true + + # make issues output unique by line, default is true + uniq-by-line: true + + # add a prefix to the output file references; default is no prefix + path-prefix: "" + + # sorts results by: filepath, line and column + sort-results: false + + +# all available settings of specific linters +linters-settings: + gofmt: + # simplify code: gofmt with `-s` option, true by default + simplify: true + staticcheck: + # Select the Go version to target. The default is '1.13'. + go: "1.19" + # https://staticcheck.io/docs/options#checks + checks: ["all"] + stylecheck: + # Select the Go version to target. The default is '1.13'. + go: "1.19" + # https://staticcheck.io/docs/options#checks + checks: ["all"] + errcheck: + # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`; + # default is false: such cases aren't reported by default. + check-blank: true + +linters: + enable: + # go install github.com/kisielk/errcheck@latest + # go install github.com/gordonklaus/ineffassign@latest + # go install honnef.co/go/tools/cmd/staticcheck@latest + # go install gitlab.com/opennota/check/cmd/varcheck@latest + # go install github.com/go-critic/go-critic/cmd/gocritic@latest + - errcheck + - staticcheck + - stylecheck + - ineffassign + - varcheck + - gofmt + - gocritic + - wsl + fast: false diff --git a/factory.go b/factory.go new file mode 100644 index 0000000..ab1fe34 --- /dev/null +++ b/factory.go @@ -0,0 +1,216 @@ +package clientfactory + +import ( + "fmt" + "time" + + "codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2/actions" + "codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2/callbacks" + "codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2/messages" + + "codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-clientfactory/v2/iclient" + "codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-clientfactory/v2/messagesender" + + "nhooyr.io/websocket" + "nhooyr.io/websocket/wsjson" +) + +var ( + gotconfig chan (bool) +) + +type AbstractClient struct { + iclient.IClient + + MessageSender *messagesender.AbstractMessageSender + + WSScheme, WSHost, WSPath string + MaxAllowedContainers int + + NbRunningContainers int +} + +func (c *AbstractClient) Run() { + gotconfig = make(chan bool) + + // Listen to server websocker messages. + c.ReadServerEvents() + + // Retrieving configuration. + c.GetConfiguration() + <-gotconfig + + // Pinging server every x seconds to keep TCP connection alive. + c.PingServer() +} + +func (c *AbstractClient) ReadServerEvents() { + c.Log("Waiting for messages from server.") + + go func() { + for { + var ( + message messages.WSMessage + err error + ) + + if err = wsjson.Read(c.MessageSender.GetContext(), c.MessageSender.WSConnection, &message); err != nil { + panic(err) + } + + if message.Error != nil { + c.ErrorCallback(message) + } else { + + switch message.Action { + case callbacks.Log: + c.Log(message.Message) + + case callbacks.BeforeStartContainerCallback: + c.Log("Message BeforeStartContainerCallback") + c.BeforeStartContainerCallback(message) + + case callbacks.AfterStartContainerCallback: + c.Log("Message AfterStartContainerCallback") + c.AfterStartContainerCallback(message) + + case callbacks.BeforeExecContainerCallback: + c.Log("Message BeforeExecContainerCallback") + c.BeforeExecContainerCallback(message) + + case callbacks.AfterExecContainerCallback: + c.Log("Message AfterExecContainerCallback") + c.AfterExecContainerCallback(message) + + case callbacks.BeforeCreateContainerCallback: + c.Log("Message BeforeCreateContainerCallback") + c.BeforeCreateContainerCallback(message) + + case callbacks.AfterCreateContainerCallback: + c.Log("Message AfterCreateContainerCallback") + c.AfterCreateContainerCallback(message) + + case callbacks.BeforeRemoveContainerCallback: + c.Log("Message BeforeRemoveContainerCallback") + c.BeforeRemoveContainerCallback(message) + + case callbacks.AfterRemoveContainerCallback: + c.Log("Message AfterRemoveContainerCallback") + c.AfterRemoveContainerCallback(message) + + case callbacks.BeforeGetContainersCallback: + c.Log("Message BeforeGetContainersCallback") + c.BeforeGetContainersCallback(message) + + case callbacks.AfterGetContainersCallback: + c.Log("Message AfterGetContainersCallback") + c.NbRunningContainers = len(message.Containers) + + c.AfterGetContainersCallback(message) + + case callbacks.BeforeGetContainerWithSameNameCallback: + c.Log("Message BeforeGetContainerWithSameNameCallback") + c.BeforeGetContainerWithSameNameCallback(message) + + case callbacks.AfterGetContainerWithSameNameCallback: + c.Log("Message AfterGetContainerWithSameNameCallback") + c.AfterGetContainerWithSameNameCallback(message) + + case callbacks.BeforeGetContainerLogCallback: + c.Log("Message BeforeGetContainerLogCallback") + c.BeforeGetContainerLogCallback(message) + + case callbacks.AfterGetContainerLogCallback: + c.Log("Message AfterGetContainerLogCallback") + c.AfterGetContainerLogCallback(message) + + case callbacks.BeforePullImageCallback: + c.Log("Message BeforePullImageCallback") + c.BeforePullImageCallback(message) + + case callbacks.AfterPullImageCallback: + c.Log("Message AfterPullImageCallback") + c.AfterPullImageCallback(message) + + case callbacks.BeforeGetConfigCallback: + c.Log("Message BeforeGetConfigCallback") + c.BeforeGetConfigCallback(message) + + case callbacks.AfterGetConfigCallback: + c.Log("Message AfterGetConfigCallback") + c.MaxAllowedContainers = message.Config.MaxAllowedContainers + gotconfig <- true + + c.AfterGetConfigCallback(message) + + case callbacks.BeforePingCallback: + c.BeforePingCallback(message) + + case callbacks.AfterPingCallback: + c.AfterPingCallback(message) + + case callbacks.BeforeTestCallback: + c.BeforeTestCallback(message) + + case callbacks.AfterTestCallback: + c.AfterTestCallback(message) + + case callbacks.BeforeTestErrorCallback: + c.BeforeTestErrorCallback(message) + + case callbacks.AfterTestErrorCallback: + c.AfterTestErrorCallback(message) + + default: + c.Log(fmt.Sprintf("unexpected message received: %+v", message)) + } + } + + } + }() +} + +func (c *AbstractClient) ConnectServer() { + var ( + err error + ) + + wsURL := fmt.Sprintf("%s://%s%sws/", c.WSScheme, c.WSHost, c.WSPath) + + c.Log("Connecting to websocket at " + wsURL) + + if c.MessageSender.WSConnection, _, err = websocket.Dial(c.MessageSender.GetContext(), wsURL, c.MessageSender.GetDialOptions()); err != nil { + panic(err) + } +} + +func (c *AbstractClient) GetConfiguration() { + c.Log("Getting configuration.") + + if err := wsjson.Write(c.MessageSender.GetContext(), c.MessageSender.WSConnection, + messages.WSMessage{ + Action: actions.GetConfig, + }, + ); err != nil { + panic(err) + } +} + +func (c *AbstractClient) PingServer() { + c.Log("Pinging server.") + + go func() { + message := messages.WSMessage{ + Action: actions.Ping, + } + + for { + err := wsjson.Write(c.MessageSender.GetContext(), c.MessageSender.WSConnection, message) + if err != nil { + panic(err) + } + + time.Sleep(30 * time.Second) + } + }() +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..32d6eb9 --- /dev/null +++ b/go.mod @@ -0,0 +1,20 @@ +module codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-clientfactory/v2 + +go 1.19 + +require ( + codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2 v2.0.0-20220905134948-382dd0bb6a40 + github.com/docker/docker v20.10.17+incompatible + nhooyr.io/websocket v1.8.7 +) + +require ( + github.com/docker/go-connections v0.4.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/klauspost/compress v1.15.9 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.0.2 // indirect +) + +// replace codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2 => /home/thbellem/workspace/workspace_go/src/codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..305036a --- /dev/null +++ b/go.sum @@ -0,0 +1,116 @@ +codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2 v2.0.0-20220518150401-ba5cd613b3ed h1:NjYlFI4M76YkEAFrmEH67czp+keOqP4o4aXBlZHf/hc= +codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2 v2.0.0-20220518150401-ba5cd613b3ed/go.mod h1:+WAHZHR8U1lAxbBTcIVteE0l4NOtVPBBX23g/JH5s04= +codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2 v2.0.0-20220705085106-ea5914d79d2a h1:fhSeZG8qYqFkfkidSJKPA9H6w1Q6snNtj2WAKoCvTDU= +codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2 v2.0.0-20220705085106-ea5914d79d2a/go.mod h1:V0N5z2WX2KuygdIcnIUJQhuLG4rA2I59hsTSaV8lV/0= +codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2 v2.0.0-20220705124009-2bcb3c889bd1 h1:SGkyKaOuCbvFooc3Pb3Rov4a56RBQY0cdXEiyEBVf7Q= +codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2 v2.0.0-20220705124009-2bcb3c889bd1/go.mod h1:V0N5z2WX2KuygdIcnIUJQhuLG4rA2I59hsTSaV8lV/0= +codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2 v2.0.0-20220905134948-382dd0bb6a40 h1:ou1weZVETrbacumoahqQKL/hpZeBvhqOsSWJyfrK328= +codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2 v2.0.0-20220905134948-382dd0bb6a40/go.mod h1:MSH3IGekA6C4WhkkYoVYzTkmPoERMLJHjudjaMDjSwQ= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE= +github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +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 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= +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 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +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/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.15.4 h1:1kn4/7MepF/CHmYub99/nNX8az0IJjfSOU/jbnTVfqQ= +github.com/klauspost/compress v1.15.4/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/compress v1.15.6 h1:6D9PcO8QWu0JyaQ2zUMmu16T1T+zjjEpP91guRsvDfY= +github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/compress v1.15.7 h1:7cgTQxJCU/vy+oP/E3B9RGbQTgbiVzIJWIKOLoAsPok= +github.com/klauspost/compress v1.15.7/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= +github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +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/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +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/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +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/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +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/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +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/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +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-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +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/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +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-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +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/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= +nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= diff --git a/iclient/iclient.go b/iclient/iclient.go new file mode 100644 index 0000000..d67f7a2 --- /dev/null +++ b/iclient/iclient.go @@ -0,0 +1,35 @@ +package iclient + +import ( + "codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2/messages" +) + +type IClient interface { + Log(message string) + ErrorCallback(messages.WSMessage) + + BeforeStartContainerCallback(messages.WSMessage) + AfterStartContainerCallback(messages.WSMessage) + BeforeCreateContainerCallback(messages.WSMessage) + AfterCreateContainerCallback(messages.WSMessage) + BeforeExecContainerCallback(messages.WSMessage) + AfterExecContainerCallback(messages.WSMessage) + BeforeRemoveContainerCallback(messages.WSMessage) + AfterRemoveContainerCallback(messages.WSMessage) + BeforeGetContainersCallback(messages.WSMessage) + AfterGetContainersCallback(messages.WSMessage) + BeforeGetContainerWithSameNameCallback(messages.WSMessage) + AfterGetContainerWithSameNameCallback(messages.WSMessage) + BeforeGetContainerLogCallback(messages.WSMessage) + AfterGetContainerLogCallback(messages.WSMessage) + BeforePullImageCallback(messages.WSMessage) + AfterPullImageCallback(messages.WSMessage) + BeforeGetConfigCallback(messages.WSMessage) + AfterGetConfigCallback(messages.WSMessage) + BeforePingCallback(messages.WSMessage) + AfterPingCallback(messages.WSMessage) + BeforeTestCallback(messages.WSMessage) + AfterTestCallback(messages.WSMessage) + BeforeTestErrorCallback(messages.WSMessage) + AfterTestErrorCallback(messages.WSMessage) +} diff --git a/messagesender/messagesender.go b/messagesender/messagesender.go new file mode 100644 index 0000000..3c2aeaf --- /dev/null +++ b/messagesender/messagesender.go @@ -0,0 +1,128 @@ +package messagesender + +import ( + "context" + "encoding/base64" + "encoding/json" + + "codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2/actions" + "codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2/credentials" + "codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2/messages" + "codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerrunner-common/v2/models" + "github.com/docker/docker/api/types" + "nhooyr.io/websocket" + "nhooyr.io/websocket/wsjson" +) + +type IMessageSender interface { + GetContext() context.Context + GetCancelFunc() context.CancelFunc + GetDialOptions() *websocket.DialOptions +} + +type AbstractMessageSender struct { + IMessageSender + + WSConnection *websocket.Conn +} + +func (ms *AbstractMessageSender) GetRunningContainers() { + if err := wsjson.Write(ms.GetContext(), ms.WSConnection, + messages.WSMessage{ + Action: actions.GetContainers, + }, + ); err != nil { + panic(err) + } +} + +func (ms *AbstractMessageSender) GetContainerLog(containerID string) { + message := messages.WSMessage{ + Action: actions.GetContainerLog, + Container: models.CodeFirstContainer{ + ID: containerID, + }} + + if err := wsjson.Write(ms.GetContext(), ms.WSConnection, message); err != nil { + panic(err) + } +} + +func (ms *AbstractMessageSender) RemoveContainer(containerID string) { + message := messages.WSMessage{ + Action: actions.RemoveContainer, + Container: models.CodeFirstContainer{ + ID: containerID, + }} + + if err := wsjson.Write(ms.GetContext(), ms.WSConnection, message); err != nil { + panic(err) + } +} + +func (ms *AbstractMessageSender) ExecContainer(containerName, user string, cmd, env []string) { + message := messages.WSMessage{ + Action: actions.ExecContainer, + Container: models.CodeFirstContainer{ + Name: containerName, + }, + Exec: types.ExecConfig{ + User: user, + Cmd: cmd, + Env: env, + }, + } + + if err := wsjson.Write(ms.GetContext(), ms.WSConnection, message); err != nil { + panic(err) + } +} + +func (ms *AbstractMessageSender) StartContainer(imageName, containerName, username, password string, private, overwrite bool, env []string) { + userCredentials := credentials.RegistryCredentials{ + Username: username, + Password: password, + } + + marshalUserCredentials, err := json.Marshal(userCredentials) + if err != nil { + panic(err) + } + + message := messages.WSMessage{ + Action: actions.StartContainer, + Container: models.CodeFirstContainer{ + ImageURL: imageName, + Name: containerName, + Base64Credentials: base64.StdEncoding.EncodeToString(marshalUserCredentials), + Env: env, + Private: private, + Overwrite: overwrite, + }} + + if err := wsjson.Write(ms.GetContext(), ms.WSConnection, message); err != nil { + panic(err) + } +} + +func (ms *AbstractMessageSender) Test() { + if err := wsjson.Write(ms.GetContext(), ms.WSConnection, + messages.WSMessage{ + Action: actions.Test, + Message: "this is a test message", + }, + ); err != nil { + panic(err) + } +} + +func (ms *AbstractMessageSender) TestError() { + if err := wsjson.Write(ms.GetContext(), ms.WSConnection, + messages.WSMessage{ + Action: actions.TestError, + Message: "this is a test error message", + }, + ); err != nil { + panic(err) + } +}