diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ed72e30 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +/vendor +/temp/* +/docker/Dockerfile* +/docker/docker-compose*.yml +/*.ps1 +/.github diff --git a/.github/workflows/ci-pip-services3-rpc-go.yml b/.github/workflows/ci-pip-services3-rpc-go.yml new file mode 100644 index 0000000..d6545d1 --- /dev/null +++ b/.github/workflows/ci-pip-services3-rpc-go.yml @@ -0,0 +1,55 @@ +name: Pip.Services RPC toolkit in Go + +on: + push: + paths: + - '**' + - '!README.md' + +jobs: + Default: + runs-on: ubuntu-16.04 + if: "!contains(github.event.head_commit.message, '[skip-ci]')" + steps: + - uses: actions/checkout@main + + ############# Prepare ############# + + - name: Save build number and component version + id: build_info + run: | + echo "##[set-output name=build_number;]$GITHUB_RUN_NUMBER" + echo "##[set-output name=component_version;]$(jq -r '.version' ./component.json)" + echo "##[set-output name=component_name;]$(jq -r '.name' ./component.json)" + + - name: Install powershell + run: | + sudo apt-get update + sudo apt-get install -y wget apt-transport-https + wget -q https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb + sudo dpkg -i packages-microsoft-prod.deb + sudo apt-get update + sudo apt-get install -y powershell + + ############# Build and test ############# + + # - name: Build the component + # run: ./build.ps1 + + - name: Test the component + run: ./test.ps1 + + ############# Release ############# + + - name: Tag branch with the build number + uses: tvdias/github-tagger@v0.0.1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + tag: "v${{ steps.build_info.outputs.component_version }}-${{ steps.build_info.outputs.build_number }}" + + ############# Clear ############# + + - name: Clean temporary build artifacts + if: ${{ always() }} + run: ./clean.ps1 + \ No newline at end of file diff --git a/.gitignore b/.gitignore index 842a33f..1418660 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,3 @@ +.DS_Store /dist -/vendor -/data/configs.test.json -/data/device_configs.json -/docker/id_rsa* -*.exe -*.tmp -/.vscode \ No newline at end of file +go.sum diff --git a/Readme.md b/Readme.md index a44885c..f9e126e 100644 --- a/Readme.md +++ b/Readme.md @@ -1,17 +1,61 @@ -# Pip.Services Logo
RPC components for Golang +# Pip.Services Logo
Remote Procedure Calls Golang -This component library is a part of the [Pip.Services](https://github.com/pip-services/pip-services) project. -It contains the Remote Procedure Calls (RPC). +This module is a part of the [Pip.Services](http://pipservices.org) polyglot microservices toolkit. -Quick Links: +The rpc module provides the synchronous communication using local calls or the HTTP(S) protocol. It contains both server and client side implementations. -* [Downloads](https://github.com/pip-services3-go/pip-services3-rpc-go/blob/master/docs/Downloads.md) +The module contains the following packages: +- [**Auth**](https://godoc.org/github.com/pip-services3-go/pip-services3-rpc-go/auth) - authentication and authorization components +- [**Build**](https://godoc.org/github.com/pip-services3-go/pip-services3-rpc-go/build) - HTTP service factory +- [**Clients**](https://godoc.org/github.com/pip-services3-go/pip-services3-rpc-go/clients) - mechanisms for retrieving connection settings from the microservice’s configuration and providing clients and services with these settings +- [**Connect**](https://godoc.org/github.com/pip-services3-go/pip-services3-rpc-go/connect) - helper module to retrieve connections for HTTP-based services and clients +- [**Services**](https://godoc.org/github.com/pip-services3-go/pip-services3-rpc-go/services) - basic implementation of services for connecting via the HTTP/REST protocol and using the Commandable pattern over HTTP + + Quick links: + +* [Your first microservice in Node.js](https://www.pipservices.org/docs/quickstart/nodejs) +* [Data Microservice. Step 5](https://www.pipservices.org/docs/tutorials/data-microservice/service) +* [Microservice Facade](https://www.pipservices.org/docs/tutorials/microservice-facade/microservice-facade-main) +* [Client Library. Step 2](https://www.pipservices.org/docs/tutorials/client-lib/direct-client) +* [Client Library. Step 3](https://www.pipservices.org/docs/tutorials/client-lib/http-client) * [API Reference](https://godoc.org/github.com/pip-services3-go/pip-services3-rpc-go/) -* [Configuration](https://github.com/pip-services3-go/pip-services3-rpc-go/blob/master/docs/Configuration.md) -* [Building and Testing](https://github.com/pip-services3-go/pip-services3-rpc-go/blob/master/docs/Development.md) -* [Contributing](https://github.com/pip-services3-go/pip-services3-rpc-go/blob/master/docs/Development.md#contrib) +* [Change Log](CHANGELOG.md) +* [Get Help](https://www.pipservices.org/community/help) +* [Contribute](https://www.pipservices.org/community/contribute) + + +## Use + +Get the package from the Github repository: +```bash +go get -u github.com/pip-services3-go/pip-services3-rpc-go@latest +``` + +## Develop + +For development you shall install the following prerequisites: +* Golang v1.12+ +* Visual Studio Code or another IDE of your choice +* Docker +* Git + +Run automated tests: +```bash +go test -v ./test/... +``` + +Generate API documentation: +```bash +./docgen.ps1 +``` + +Before committing changes run dockerized test as: +```bash +./test.ps1 +./clear.ps1 +``` -## Acknowledgements +## Contacts The library is created and maintained by **Sergey Seroukhov** and **Levichev Dmitry**. diff --git a/build.ps1 b/build.ps1 new file mode 100755 index 0000000..b99f951 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,36 @@ +#!/usr/bin/env pwsh + +Set-StrictMode -Version latest +$ErrorActionPreference = "Stop" + +# Generate image and container names using the data in the "component.json" file +$component = Get-Content -Path "component.json" | ConvertFrom-Json + +# Get buildnumber from github actions +if ($env:GITHUB_RUN_NUMBER -ne $null) { + $component.build = $env:GITHUB_RUN_NUMBER + Set-Content -Path "component.json" -Value $($component | ConvertTo-Json) +} + +$buildImage="$($component.registry)/$($component.name):$($component.version)-$($component.build)-build" +$container=$component.name + +# Remove build files +if (Test-Path "./dist") { + $null = Remove-Item -Recurse -Force -Path "./dist/*" +} else { + $null = New-Item -ItemType Directory -Force -Path "./dist" +} + +# Build docker image +docker build -f docker/Dockerfile.build -t $buildImage . + +# Create and copy compiled files, then destroy +docker create --name $container $buildImage +docker cp "$($container):/app/run" ./dist/run +docker rm $container + +if (!(Test-Path "./dist")) { + Write-Host "dist folder doesn't exist in root dir. Build failed. Watch logs above." + exit 1 +} diff --git a/changelog.md b/changelog.md index 19d626f..4837551 100644 --- a/changelog.md +++ b/changelog.md @@ -1,7 +1,53 @@ -# RPC components for Pip.Services in Golang Changelog +# Pip.Services Logo
Remote Procedure Calls Golang Changelog -## 1.0.1 (2020-08-05) +## 1.0.8-1.0.11 (2020-12-02) ### Features -* Fix response error method in HttpResponseSender + +* Added helper methods to RestOperations +* Change RegisterWithAuth methods + +### Bug Fixes +* Fix authorizer + +## 1.0.7 (2020-11-20) + +### Features + +* Added swagger support + +## 1.0.5-1.0.6 (2020-11-13) + +### Features + +* Added helper methods + +## 1.0.3-1.0.4 (2020-11-12) + +### Features + +* Added helper methods in RestService + +### Bug Fixes +* Fix signature CallCommand in CommandableHttpClient + +## 1.0.1-1.0.2 (2020-08-05) + +### Features + +* Added error handler in Call method of RestClient + +### Bug Fixes +* Fix response error method + +## 1.0.0 (2020-01-28) + +Initial public release + +### Features + +* **build** HTTP service factory +* **clients** mechanisms for retrieving connection settings +* **connect** helper module to retrieve connections services and clients +* **services** basic implementation of services for connecting diff --git a/clean.ps1 b/clean.ps1 new file mode 100755 index 0000000..d3d2307 --- /dev/null +++ b/clean.ps1 @@ -0,0 +1,24 @@ +#!/usr/bin/env pwsh + +# Recreate image names using the data in the "component.json" file +$component = Get-Content -Path "component.json" | ConvertFrom-Json +$buildImage="$($component.registry)/$($component.name):$($component.version)-$($component.build)-build" +$docsImage="$($component.registry)/$($component.name):$($component.version)-$($component.build)-docs" +$testImage="$($component.registry)/$($component.name):$($component.version)-$($component.build)-test" + +# Clean up build directories +Get-ChildItem -Path "." -Include "exe" -Recurse | foreach($_) { Remove-Item -Force -Recurse $_.FullName } + +# Remove docker images +docker rmi $buildImage --force +docker rmi $docsImage --force +docker rmi $testImage --force +docker image prune --force +docker rmi -f $(docker images -f "dangling=true" -q) # remove build container if build fails + +# Remove existed containers +$exitedContainers = docker ps -a | Select-String -Pattern "Exit" +foreach($c in $exitedContainers) { docker rm $c.ToString().Split(" ")[0] } + +# Remove unused volumes +docker volume rm -f $(docker volume ls -f "dangling=true") diff --git a/clients/CommandableHttpClient.go b/clients/CommandableHttpClient.go index 6fa9783..3f1aeaf 100644 --- a/clients/CommandableHttpClient.go +++ b/clients/CommandableHttpClient.go @@ -15,17 +15,17 @@ in body object. Configuration parameters: -base_route: base route for remote URI -- connection(s): - - discovery_key: (optional) a key to retrieve the connection from connect.idiscovery.html IDiscovery]] - - protocol: connection protocol: http or https - - host: host name or IP address - - port: port number - - uri: resource URI or connection string with all parameters in it -- options: - - retries: number of retries (default: 3) - - connect_timeout: connection timeout in milliseconds (default: 10 sec) - - timeout: invocation timeout in milliseconds (default: 10 sec) + base_route: base route for remote URI + - connection(s): + - discovery_key: (optional) a key to retrieve the connection from connect.idiscovery.html IDiscovery]] + - protocol: connection protocol: http or https + - host: host name or IP address + - port: port number + - uri: resource URI or connection string with all parameters in it + - options: + - retries: number of retries (default: 3) + - connect_timeout: connection timeout in milliseconds (default: 10 sec) + - timeout: invocation timeout in milliseconds (default: 10 sec) References: @@ -72,7 +72,7 @@ type CommandableHttpClient struct { // NewCommandableHttpClient is creates a new instance of the client. // Parameters: -// - baseRoute string a base route for remote service. +// - baseRoute string a base route for remote service. // Returns: *CommandableHttpClient // pointer on new instance func NewCommandableHttpClient(baseRoute string) *CommandableHttpClient { @@ -86,10 +86,10 @@ func NewCommandableHttpClient(baseRoute string) *CommandableHttpClient { // The call is made via POST operation and all parameters are sent in body object. // The complete route to remote method is defined as baseRoute + "/" + name. // Parameters: -// - prototype reflect.Type type of returned data -// - name string a name of the command to call. -// - correlationId string (optional) transaction id to trace execution through call chain. -// - params cdata.StringValueMap command parameters. +// - prototype reflect.Type type of returned data +// - name string a name of the command to call. +// - correlationId string (optional) transaction id to trace execution through call chain. +// - params cdata.StringValueMap command parameters. // Returns: result interface{}, err error // result or error. func (c *CommandableHttpClient) CallCommand(prototype reflect.Type, name string, correlationId string, params *cdata.AnyValueMap) (result interface{}, err error) { diff --git a/clients/Convert.go b/clients/Convert.go index b333761..b74cd6b 100644 --- a/clients/Convert.go +++ b/clients/Convert.go @@ -7,8 +7,8 @@ import ( //ConvertComandResult method helps get correct result from JSON by prototype //Parameters: -// - comRes interface{} input JSON string -// - prototype reflect.Type output object prototype +// - comRes interface{} input JSON string +// - prototype reflect.Type output object prototype // Returns: convRes interface{}, err error func ConvertComandResult(comRes interface{}, prototype reflect.Type) (convRes interface{}, err error) { diff --git a/clients/RestClient.go b/clients/RestClient.go index faf437b..e96b201 100644 --- a/clients/RestClient.go +++ b/clients/RestClient.go @@ -22,17 +22,17 @@ import ( RestClient is abstract client that calls remove endpoints using HTTP/REST protocol. Configuration parameters: -- base_route: base route for remote URI -- connection(s): - - discovery_key: (optional) a key to retrieve the connection from IDiscovery - - protocol: connection protocol: http or https - - host: host name or IP address - - port: port number - - uri: resource URI or connection string with all parameters in it -- options: - - retries: number of retries (default: 3) - - connectTimeout: connection timeout in milliseconds (default: 10 sec) - - timeout: invocation timeout in milliseconds (default: 10 sec) + - base_route: base route for remote URI + - connection(s): + - discovery_key: (optional) a key to retrieve the connection from IDiscovery + - protocol: connection protocol: http or https + - host: host name or IP address + - port: port number + - uri: resource URI or connection string with all parameters in it + - options: + - retries: number of retries (default: 3) + - connectTimeout: connection timeout in milliseconds (default: 10 sec) + - timeout: invocation timeout in milliseconds (default: 10 sec) References: - *:logger:*:*:1.0 (optional) ILogger components to pass log messages @@ -73,7 +73,6 @@ See CommandableHttpService ... */ - type RestClient struct { defaultConfig cconf.ConfigParams //The HTTP client. diff --git a/component.json b/component.json new file mode 100644 index 0000000..5c50b89 --- /dev/null +++ b/component.json @@ -0,0 +1,6 @@ +{ + "name": "pip-services3-rpc-go", + "registry": "github.com/pip-services3-go", + "version": "3.0.0", + "build": 0 +} \ No newline at end of file diff --git a/connect/HttpConnectionResolver.go b/connect/HttpConnectionResolver.go index d0df7a9..ef9486c 100644 --- a/connect/HttpConnectionResolver.go +++ b/connect/HttpConnectionResolver.go @@ -19,15 +19,15 @@ and validate connection parameters before returning them. Configuration parameters: -- connection: - - discovery_key: (optional) a key to retrieve the connection from IDiscovery - - ... other connection parameters - -- connections: alternative to connection - - [connection params 1]: first connection parameters - - ... - - [connection params N]: Nth connection parameters - - ... + - connection: + - discovery_key: (optional) a key to retrieve the connection from IDiscovery + - ... other connection parameters + + - connections: alternative to connection + - [connection params 1]: first connection parameters + - ... + - [connection params N]: Nth connection parameters + - ... References: diff --git a/docgen.ps1 b/docgen.ps1 new file mode 100755 index 0000000..0c41493 --- /dev/null +++ b/docgen.ps1 @@ -0,0 +1,40 @@ +#!/usr/bin/env pwsh + +Set-StrictMode -Version latest +$ErrorActionPreference = "Stop" + +# Generate image and container names using the data in the "component.json" file +$component = Get-Content -Path "component.json" | ConvertFrom-Json + +$docImage="$($component.registry)/$($component.name):$($component.version)-$($component.build)-docs" +$container=$component.name + +# Remove build files +if (Test-Path "./docs") { + Remove-Item -Recurse -Force -Path "./docs/*" +} else { + $null = New-Item -ItemType Directory -Force -Path "./docs" +} + +# Build docker image +docker build -f docker/Dockerfile.docgen -t $docImage . + +# Run docgen container +docker run -d --name $container $docImage +# Wait it to start +Start-Sleep -Seconds 2 +# Generate docs +docker exec -ti $container /bin/bash -c "wget -r -np -N -E -p -k http://localhost:6060/pkg/" +# Copy docs from container +docker cp "$($container):/app/localhost:6060/pkg" ./docs/pkg +docker cp "$($container):/app/localhost:6060/lib" ./docs/lib +# Remove docgen container +docker rm $container --force + +Write-Output "" > ./docs/index.html + +# Verify docs +if (!(Test-Path "./docs")) { + Write-Host "docs folder doesn't exist in root dir. Watch logs above." + exit 1 +} diff --git a/docker/Dockerfile.build b/docker/Dockerfile.build new file mode 100644 index 0000000..119de74 --- /dev/null +++ b/docker/Dockerfile.build @@ -0,0 +1,22 @@ +FROM golang:1.13 + +# Set environment variables for Go +ENV GO111MODULE=on \ + CGO_ENABLED=0 \ + GOOS=linux \ + GOARCH=amd64 + +# Set a working directory +WORKDIR /app + +# Copy the package files +COPY go.mod ./ + +# Install all go_modules +RUN go mod download + +# Copy the package files +COPY . . + +# Build the project +RUN go build -o /go/bin/run . diff --git a/docker/Dockerfile.docgen b/docker/Dockerfile.docgen new file mode 100644 index 0000000..7c51194 --- /dev/null +++ b/docker/Dockerfile.docgen @@ -0,0 +1,14 @@ +FROM golang:1.13 + +# Set environment variables for Go +ENV GO111MODULE=on + +WORKDIR /app + +RUN go install golang.org/x/tools/cmd/godoc + +WORKDIR /app + +COPY . ./src + +ENTRYPOINT godoc -http=0.0.0.0:6060 -v -goroot=. \ No newline at end of file diff --git a/docker/Dockerfile.test b/docker/Dockerfile.test new file mode 100644 index 0000000..c4c7a20 --- /dev/null +++ b/docker/Dockerfile.test @@ -0,0 +1,22 @@ +FROM golang:1.13 + +# Set environment variables for Go +ENV GO111MODULE=on \ + CGO_ENABLED=0 \ + GOOS=linux \ + GOARCH=amd64 + +# Set a working directory +WORKDIR /app + +# Copy the package files +COPY go.mod ./ + +# Install all go_modules +RUN go mod download + +# Copy the entire project +COPY . . + +# Specify the command from running tests +CMD go test -v ./test/... \ No newline at end of file diff --git a/docker/docker-compose.test.yml b/docker/docker-compose.test.yml new file mode 100644 index 0000000..6896bc8 --- /dev/null +++ b/docker/docker-compose.test.yml @@ -0,0 +1,8 @@ +version: '3.3' + +services: + test: + build: + context: .. + dockerfile: docker/Dockerfile.test + image: ${IMAGE:-pipdevs/test} diff --git a/services/CommandableHttpService.go b/services/CommandableHttpService.go index cd5d6a8..a63c75b 100644 --- a/services/CommandableHttpService.go +++ b/services/CommandableHttpService.go @@ -22,16 +22,16 @@ HTTP-based remote interface. Configuration parameters: -- base_route: base route for remote URI -- dependencies: - - endpoint: override for HTTP Endpoint dependency - - controller: override for Controller dependency -- connection(s): - - discovery_key: (optional) a key to retrieve the connection from IDiscovery - - protocol: connection protocol: http or https - - host: host name or IP address - - port: port number - - uri: resource URI or connection string with all parameters in it + - base_route: base route for remote URI + - dependencies: + - endpoint: override for HTTP Endpoint dependency + - controller: override for Controller dependency + - connection(s): + - discovery_key: (optional) a key to retrieve the connection from IDiscovery + - protocol: connection protocol: http or https + - host: host name or IP address + - port: port number + - uri: resource URI or connection string with all parameters in it References: diff --git a/services/HeartbeatRestService.go b/services/HeartbeatRestService.go index f9514cf..bce090f 100644 --- a/services/HeartbeatRestService.go +++ b/services/HeartbeatRestService.go @@ -18,16 +18,16 @@ container orchestrators. Configuration parameters: -- baseroute: base route for remote URI (default: "") -- route: route to heartbeat operation (default: "heartbeat") -- dependencies: - - endpoint: override for HTTP Endpoint dependency -- connection(s): - - discovery_key: (optional) a key to retrieve the connection from IDiscovery - - protocol: connection protocol: http or https - - host: host name or IP address - - port: port number - - uri: resource URI or connection string with all parameters in it + - baseroute: base route for remote URI (default: "") + - route: route to heartbeat operation (default: "heartbeat") + - dependencies: + - endpoint: override for HTTP Endpoint dependency + - connection(s): + - discovery_key: (optional) a key to retrieve the connection from IDiscovery + - protocol: connection protocol: http or https + - host: host name or IP address + - port: port number + - uri: resource URI or connection string with all parameters in it References: diff --git a/services/HttpEndpoint.go b/services/HttpEndpoint.go index aa17114..3815d89 100644 --- a/services/HttpEndpoint.go +++ b/services/HttpEndpoint.go @@ -26,13 +26,13 @@ Configuration parameters: Parameters to pass to the configure method for component configuration: -- connection(s) - the connection resolver"s connections: + - connection(s) - the connection resolver"s connections: - "connection.discovery_key" - the key to use for connection resolving in a discovery service; - "connection.protocol" - the connection"s protocol; - "connection.host" - the target host; - "connection.port" - the target port; - "connection.uri" - the target URI. -- credential - the HTTPS credentials: + - credential - the HTTPS credentials: - "credential.ssl_key_file" - the SSL func (c *HttpEndpoint )key in PEM - "credential.ssl_crt_file" - the SSL certificate in PEM - "credential.ssl_ca_file" - the certificate authorities (root cerfiticates) in PEM @@ -42,9 +42,9 @@ References: A logger, counters, and a connection resolver can be referenced by passing the following references to the object"s setReferences method: -- logger: "*:logger:*:*:1.0"; -- counters: "*:counters:*:*:1.0"; -- discovery: "*:discovery:*:*:1.0" (for the connection resolver). + - logger: "*:logger:*:*:1.0"; + - counters: "*:counters:*:*:1.0"; + - discovery: "*:discovery:*:*:1.0" (for the connection resolver). Examples: @@ -53,7 +53,6 @@ Examples: endpoint.SetReferences(references); ... endpoint.Open(correlationId) - */ type HttpEndpoint struct { defaultConfig *cconf.ConfigParams @@ -257,7 +256,7 @@ func (c *HttpEndpoint) doMaintenance(next http.Handler) http.Handler { // Close method are closes this endpoint and the REST server (service) that was opened earlier. // Parameters: -// - correlationId string (optional) transaction id to trace execution through call chain. +// - correlationId string (optional) transaction id to trace execution through call chain. // Returns: error // an error if one is raised. func (c *HttpEndpoint) Close(correlationId string) error { @@ -279,7 +278,7 @@ func (c *HttpEndpoint) Close(correlationId string) error { // Registers a registerable object for dynamic endpoint discovery. // Parameters: -// - registration IRegisterable implements of IRegisterable interface. +// - registration IRegisterable implements of IRegisterable interface. // See IRegisterable func (c *HttpEndpoint) Register(registration IRegisterable) { c.registrations = append(c.registrations, registration) @@ -288,7 +287,7 @@ func (c *HttpEndpoint) Register(registration IRegisterable) { // Unregisters a registerable object, so that it is no longer used in dynamic // endpoint discovery. // Parameters: -// - registration IRegisterable the registration to remove. +// - registration IRegisterable the registration to remove. // See IRegisterable func (c *HttpEndpoint) Unregister(registration IRegisterable) { for i := 0; i < len(c.registrations); { @@ -318,10 +317,10 @@ func (c *HttpEndpoint) fixRoute(route string) string { } // RegisterRoute method are registers an action in this objects REST server (service) by the given method and route. -// - method string the HTTP method of the route. -// - route string the route to register in this object"s REST server (service). -// - schema *cvalid.Schema the schema to use for parameter validation. -// - action http.HandlerFunc the action to perform at the given route. +// - method string the HTTP method of the route. +// - route string the route to register in this object"s REST server (service). +// - schema *cvalid.Schema the schema to use for parameter validation. +// - action http.HandlerFunc the action to perform at the given route. func (c *HttpEndpoint) RegisterRoute(method string, route string, schema *cvalid.Schema, action http.HandlerFunc) { @@ -371,11 +370,11 @@ func (c *HttpEndpoint) RegisterRoute(method string, route string, schema *cvalid // RegisterRouteWithAuth method are registers an action with authorization in this objects REST server (service) // by the given method and route. // Parameters: -// - method string the HTTP method of the route. -// - route string the route to register in this object"s REST server (service). -// - schema *cvalid.Schema the schema to use for parameter validation. -// - authorize the authorization interceptor -// - action the action to perform at the given route. +// - method string the HTTP method of the route. +// - route string the route to register in this object"s REST server (service). +// - schema *cvalid.Schema the schema to use for parameter validation. +// - authorize the authorization interceptor +// - action the action to perform at the given route. func (c *HttpEndpoint) RegisterRouteWithAuth(method string, route string, schema *cvalid.Schema, authorize func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc), action http.HandlerFunc) { @@ -391,8 +390,8 @@ func (c *HttpEndpoint) RegisterRouteWithAuth(method string, route string, schema } // RegisterInterceptor method are registers a middleware action for the given route. -// - route the route to register in this object"s REST server (service). -// - action the middleware action to perform at the given route. +// - route the route to register in this object"s REST server (service). +// - action the middleware action to perform at the given route. func (c *HttpEndpoint) RegisterInterceptor(route string, action func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)) { route = c.fixRoute(route) diff --git a/services/HttpRequestDetector.go b/services/HttpRequestDetector.go index c935510..d789936 100644 --- a/services/HttpRequestDetector.go +++ b/services/HttpRequestDetector.go @@ -14,9 +14,9 @@ type THttpRequestDetector struct { } // DetectPlatform method are detects the platform (using "user-agent") from which the given HTTP request was made. -// - req *http.Request an HTTP request to process. -// Returns the detected platform and version. Detectable platforms: "mobile", "iphone", -// "ipad", "macosx", "android", "webos", "mac", "windows". Otherwise - "unknown" will +// - req *http.Request an HTTP request to process. +// Returns the detected platform and version. Detectable platforms: "mobile", "iphone", +// "ipad", "macosx", "android", "webos", "mac", "windows". Otherwise - "unknown" will // be returned. func (c *THttpRequestDetector) DetectPlatform(req *http.Request) string { ua := req.Header.Get("user-agent") @@ -93,8 +93,8 @@ func (c *THttpRequestDetector) DetectPlatform(req *http.Request) string { } // Detects the browser (using "user-agent") from which the given HTTP request was made. -// - req *http.Reques an HTTP request to process. -// Returns the detected browser. Detectable browsers: "chrome", "msie", "firefox", +// - req *http.Reques an HTTP request to process. +// Returns the detected browser. Detectable browsers: "chrome", "msie", "firefox", // "safari". Otherwise - "unknown" will be returned. func (c *THttpRequestDetector) DetectBrowser(req *http.Request) string { @@ -133,7 +133,7 @@ func (c *THttpRequestDetector) DetectBrowser(req *http.Request) string { // DetectAddress method are detects the IP address from which the given HTTP request was received. // - req *http.Reques an HTTP request to process. -// Returns the detected IP address (without a port). If no IP is detected - +// Returns the detected IP address (without a port). If no IP is detected - // nil will be returned. func (c *THttpRequestDetector) DetectAddress(req *http.Request) string { var ip string @@ -171,16 +171,16 @@ func (c *THttpRequestDetector) DetectAddress(req *http.Request) string { } // DetectServerHost method are detects the host name of the request"s destination server. -// - req *http.Request an HTTP request to process. -// Returns the destination server"s host name. +// - req *http.Request an HTTP request to process. +// Returns the destination server"s host name. func (c *THttpRequestDetector) DetectServerHost(req *http.Request) string { //TODO: Need fix this return "" + req.URL.Hostname() // socket.localAddress } // DetectServerPort method are detects the request"s destination port number. -// - req *http.Request an HTTP request to process. -// Returns the detected port number or 80 (if none are detected). +// - req *http.Request an HTTP request to process. +// Returns the detected port number or 80 (if none are detected). func (c *THttpRequestDetector) DetectServerPort(req *http.Request) string { return req.URL.Port() //socket.localPort } diff --git a/services/HttpResponseSender.go b/services/HttpResponseSender.go index c13a300..6dcdf0a 100644 --- a/services/HttpResponseSender.go +++ b/services/HttpResponseSender.go @@ -19,9 +19,9 @@ type THttpResponseSender struct { // and appropriate HTTP status code. // If status code is not defined, it uses 500 status code. // Parameters: -// - req *http.Request a HTTP request object. -// - res http.ResponseWriter a HTTP response object. -// - err error an error object to be sent. +// - req *http.Request a HTTP request object. +// - res http.ResponseWriter a HTTP response object. +// - err error an error object to be sent. func (c *THttpResponseSender) SendError(res http.ResponseWriter, req *http.Request, err error) { appErr := cerr.ApplicationError{} @@ -39,10 +39,10 @@ func (c *THttpResponseSender) SendError(res http.ResponseWriter, req *http.Reque // For nil results it returns 204 status code. // If error occur it sends ErrorDescription with approproate status code. // Parameters: -// - req *http.Request a HTTP request object. -// - res http.ResponseWriter a HTTP response object. -// - result interface{} result object to be send -// - err error an error object to be sent. +// - req *http.Request a HTTP request object. +// - res http.ResponseWriter a HTTP response object. +// - result interface{} result object to be send +// - err error an error object to be sent. func (c *THttpResponseSender) SendResult(res http.ResponseWriter, req *http.Request, result interface{}, err error) { if err != nil { HttpResponseSender.SendError(res, req, err) @@ -60,8 +60,8 @@ func (c *THttpResponseSender) SendResult(res http.ResponseWriter, req *http.Requ // SendEmptyResult are sends an empty result with 204 status code. // If error occur it sends ErrorDescription with approproate status code. -// - req *http.Request a HTTP request object. -// - res http.ResponseWriter a HTTP response object. +// - req *http.Request a HTTP request object. +// - res http.ResponseWriter a HTTP response object. func (c *THttpResponseSender) SendEmptyResult(res http.ResponseWriter, req *http.Request, err error) { if err != nil { HttpResponseSender.SendError(res, req, err) @@ -77,8 +77,8 @@ func (c *THttpResponseSender) SendEmptyResult(res http.ResponseWriter, req *http // For nil results it returns 204 status code. // If error occur it sends ErrorDescription with approproate status code. // Parameters: -// - req *http.Request a HTTP request object. -// - res http.ResponseWriter a HTTP response object. +// - req *http.Request a HTTP request object. +// - res http.ResponseWriter a HTTP response object. func (c *THttpResponseSender) SendCreatedResult(res http.ResponseWriter, req *http.Request, result interface{}, err error) { if err != nil { HttpResponseSender.SendError(res, req, err) @@ -102,8 +102,8 @@ func (c *THttpResponseSender) SendCreatedResult(res http.ResponseWriter, req *ht // For nil results it returns 204 status code. // If error occur it sends ErrorDescription with approproate status code. // Parameters: -// - req *http.Request a HTTP request object. -// - res http.ResponseWriter a HTTP response object. +// - req *http.Request a HTTP request object. +// - res http.ResponseWriter a HTTP response object. func (c *THttpResponseSender) SendDeletedResult(res http.ResponseWriter, req *http.Request, result interface{}, err error) { if err != nil { HttpResponseSender.SendError(res, req, err) diff --git a/services/RestOperations.go b/services/RestOperations.go index 2ddbc99..7c6ba8d 100644 --- a/services/RestOperations.go +++ b/services/RestOperations.go @@ -34,15 +34,15 @@ func NewRestOperations() *RestOperations { // Configure method are configures this RestOperations using the given configuration parameters. // Parameters: -// - config *cconf.ConfigParams confif parameters +// - config *cconf.ConfigParams confif parameters func (c *RestOperations) Configure(config *cconf.ConfigParams) { c.DependencyResolver.Configure(config) } // SetReferences method are sets references to this RestOperations logger, counters, and connection resolver. // Parameters: -// - references an IReferences object, containing references to a logger, counters, -// and a dependency resolver. +// - references an IReferences object, containing references to a logger, counters, +// and a dependency resolver. func (c *RestOperations) SetReferences(references crefer.IReferences) { c.Logger.SetReferences(references) c.Counters.SetReferences(references) @@ -51,7 +51,7 @@ func (c *RestOperations) SetReferences(references crefer.IReferences) { // GetCorrelationId method returns CorrelationId from request // Parameters: -// req *http.Request request +// req *http.Request request // Returns: string // retrun correlation_id or empty string func (c *RestOperations) GetCorrelationId(req *http.Request) string { @@ -61,7 +61,7 @@ func (c *RestOperations) GetCorrelationId(req *http.Request) string { // GetFilterParams method retruns filter params object from request // Parameters: -// req *http.Request request +// req *http.Request request // Returns: *cdata.FilterParams // filter params object func (c *RestOperations) GetFilterParams(req *http.Request) *cdata.FilterParams { @@ -78,7 +78,7 @@ func (c *RestOperations) GetFilterParams(req *http.Request) *cdata.FilterParams // GetPagingParams method retruns paging params object from request // Parameters: -// req *http.Request request +// req *http.Request request // Returns: *cdata.PagingParams // pagings params object func (c *RestOperations) GetPagingParams(req *http.Request) *cdata.PagingParams { @@ -97,8 +97,8 @@ func (c *RestOperations) GetPagingParams(req *http.Request) *cdata.PagingParams } // GetParam methods helps get all params from query -// - req - incoming request -// - name - parameter name +// - req - incoming request +// - name - parameter name // Returns value or empty string if param not exists func (c *RestOperations) GetParam(req *http.Request, name string) string { param := req.URL.Query().Get(name) @@ -109,8 +109,8 @@ func (c *RestOperations) GetParam(req *http.Request, name string) string { } // DecodeBody methods helps decode body -// - req - incoming request -// - target - pointer on target variable for decode +// - req - incoming request +// - target - pointer on target variable for decode // Returns error func (c *RestOperations) DecodeBody(req *http.Request, target interface{}) error { diff --git a/services/RestService.go b/services/RestService.go index 28b87ba..0083243 100644 --- a/services/RestService.go +++ b/services/RestService.go @@ -22,20 +22,20 @@ RestService Abstract service that receives remove calls via HTTP/REST protocol. Configuration parameters: -- base_route: base route for remote URI -- dependencies: - - endpoint: override for HTTP Endpoint dependency - - controller: override for Controller dependency -- connection(s): - - discovery_key: (optional) a key to retrieve the connection from IDiscovery - - protocol: connection protocol: http or https - - host: host name or IP address - - port: port number - - uri: resource URI or connection string with all parameters in it -- credential - the HTTPS credentials: - - ssl_key_file: the SSL private key in PEM - - ssl_crt_file: the SSL certificate in PEM - - ssl_ca_file: the certificate authorities (root cerfiticates) in PEM + - base_route: base route for remote URI + - dependencies: + - endpoint: override for HTTP Endpoint dependency + - controller: override for Controller dependency + - connection(s): + - discovery_key: (optional) a key to retrieve the connection from IDiscovery + - protocol: connection protocol: http or https + - host: host name or IP address + - port: port number + - uri: resource URI or connection string with all parameters in it + - credential - the HTTPS credentials: + - ssl_key_file: the SSL private key in PEM + - ssl_crt_file: the SSL certificate in PEM + - ssl_ca_file: the certificate authorities (root cerfiticates) in PEM References: @@ -152,7 +152,7 @@ func NewRestService() *RestService { // Configure method are configures component by passing configuration parameters. // Parameters: -// - config *cconf.ConfigParams configuration parameters to be set. +// - config *cconf.ConfigParams configuration parameters to be set. func (c *RestService) Configure(config *cconf.ConfigParams) { config = config.SetDefaults(c.defaultConfig) c.config = config @@ -164,7 +164,7 @@ func (c *RestService) Configure(config *cconf.ConfigParams) { // SetReferences method are sets references to dependent components. // Parameters: -// - references crefer.IReferences references to locate the component dependencies. +// - references crefer.IReferences references to locate the component dependencies. func (c *RestService) SetReferences(references crefer.IReferences) { c.references = references @@ -214,8 +214,8 @@ func (c *RestService) createEndpoint() *HttpEndpoint { // Instrument method are adds instrumentation to log calls and measure call time. // It returns a Timing object that is used to end the time measurement. // Parameters: -// - correlationId (optional) transaction id to trace execution through call chain. -// - name a method name. +// - correlationId (optional) transaction id to trace execution through call chain. +// - name a method name. // Returns Timing object to end the time measurement. func (c *RestService) Instrument(correlationId string, name string) *ccount.Timing { c.Logger.Trace(correlationId, "Executing %s method", name) @@ -225,10 +225,10 @@ func (c *RestService) Instrument(correlationId string, name string) *ccount.Timi // InstrumentError method are adds instrumentation to error handling. // Parameters: -// - correlationId string (optional) transaction id to trace execution through call chain. -// - name string a method name. -// - err error an occured error -// - result interface{} (optional) an execution result +// - correlationId string (optional) transaction id to trace execution through call chain. +// - name string a method name. +// - err error an occured error +// - result interface{} (optional) an execution result // Returns: result interface{}, err error // (optional) an execution callback func (c *RestService) InstrumentError(correlationId string, name string, errIn error, @@ -248,7 +248,7 @@ func (c *RestService) IsOpen() bool { // Open method are opens the component. // Parameters: -// - correlationId string: (optional) transaction id to trace execution through call chain. +// - correlationId string: (optional) transaction id to trace execution through call chain. // Returns: error // error or nil no errors occured. func (c *RestService) Open(correlationId string) error { @@ -275,8 +275,8 @@ func (c *RestService) Open(correlationId string) error { // Close method are closes component and frees used resources. // Parameters: -// - correlationId (optional) transaction id to trace execution through call chain. -// Returns: error +// - correlationId (optional) transaction id to trace execution through call chain. +// Returns: error // error or nil no errors occured. func (c *RestService) Close(correlationId string) error { if !c.opened { @@ -305,10 +305,10 @@ func (c *RestService) Close(correlationId string) error { // For nil results it returns 204 status code. // If error occur it sends ErrorDescription with approproate status code. // Parameters: -// - req a HTTP request object. -// - res a HTTP response object. -// - result (optional) result object to send -// - err error (optional) error objrct to send +// - req a HTTP request object. +// - res a HTTP response object. +// - result (optional) result object to send +// - err error (optional) error objrct to send func (c *RestService) SendResult(res http.ResponseWriter, req *http.Request, result interface{}, err error) { HttpResponseSender.SendResult(res, req, result, err) } @@ -322,8 +322,8 @@ func (c *RestService) SendResult(res http.ResponseWriter, req *http.Request, res // Parameters: // - req a HTTP request object. // - res a HTTP response object. -// - result (optional) result object to send -// - err error (optional) error objrct to send +// - result (optional) result object to send +// - err error (optional) error objrct to send func (c *RestService) SendCreatedResult(res http.ResponseWriter, req *http.Request, result interface{}, err error) { HttpResponseSender.SendCreatedResult(res, req, result, err) } @@ -335,10 +335,10 @@ func (c *RestService) SendCreatedResult(res http.ResponseWriter, req *http.Reque // For nil results it returns 204 status code. // If error occur it sends ErrorDescription with approproate status code. // Parameters: -// - req a HTTP request object. -// - res a HTTP response object. -// - result (optional) result object to send -// - err error (optional) error objrct to send +// - req a HTTP request object. +// - res a HTTP response object. +// - result (optional) result object to send +// - err error (optional) error objrct to send func (c *RestService) SendDeletedResult(res http.ResponseWriter, req *http.Request, result interface{}, err error) { HttpResponseSender.SendDeletedResult(res, req, result, err) } @@ -347,9 +347,9 @@ func (c *RestService) SendDeletedResult(res http.ResponseWriter, req *http.Reque // and appropriate HTTP status code. // If status code is not defined, it uses 500 status code. // Parameters: -// - req a HTTP request object. -// - res a HTTP response object. -// - error an error object to be sent. +// - req a HTTP request object. +// - res a HTTP response object. +// - error an error object to be sent. func (c *RestService) SendError(res http.ResponseWriter, req *http.Request, err error) { HttpResponseSender.SendError(res, req, err) } @@ -379,10 +379,10 @@ func (c *RestService) appendBaseRoute(route string) string { // RegisterRoute method are registers a route in HTTP endpoint. // Parameters: -// - method HTTP method: "get", "head", "post", "put", "delete" -// - route a command route. Base route will be added to this route -// - schema a validation schema to validate received parameters. -// - action an action function that is called when operation is invoked. +// - method HTTP method: "get", "head", "post", "put", "delete" +// - route a command route. Base route will be added to this route +// - schema a validation schema to validate received parameters. +// - action an action function that is called when operation is invoked. func (c *RestService) RegisterRoute(method string, route string, schema *cvalid.Schema, action func(res http.ResponseWriter, req *http.Request)) { if c.Endpoint == nil { @@ -394,11 +394,11 @@ func (c *RestService) RegisterRoute(method string, route string, schema *cvalid. // RegisterRouteWithAuth method are registers a route with authorization in HTTP endpoint. // Parameters: -// - method HTTP method: "get", "head", "post", "put", "delete" -// - route a command route. Base route will be added to this route -// - schema a validation schema to validate received parameters. -// - authorize an authorization interceptor -// - action an action function that is called when operation is invoked. +// - method HTTP method: "get", "head", "post", "put", "delete" +// - route a command route. Base route will be added to this route +// - schema a validation schema to validate received parameters. +// - authorize an authorization interceptor +// - action an action function that is called when operation is invoked. func (c *RestService) RegisterRouteWithAuth(method string, route string, schema *cvalid.Schema, authorize func(res http.ResponseWriter, req *http.Request, next http.HandlerFunc), action func(res http.ResponseWriter, req *http.Request)) { @@ -419,8 +419,8 @@ func (c *RestService) RegisterRouteWithAuth(method string, route string, schema // RegisterInterceptor method are registers a middleware for a given route in HTTP endpoint. // Parameters: -// - route a command route. Base route will be added to this route -// - action an action function that is called when middleware is invoked. +// - route a command route. Base route will be added to this route +// - action an action function that is called when middleware is invoked. func (c *RestService) RegisterInterceptor(route string, action func(res http.ResponseWriter, req *http.Request, next http.HandlerFunc)) { if c.Endpoint == nil { @@ -434,8 +434,8 @@ func (c *RestService) RegisterInterceptor(route string, } // GetParam methods helps get all params from query -// - req - incoming request -// - name - parameter name +// - req - incoming request +// - name - parameter name // Returns value or empty string if param not exists func (c *RestService) GetParam(req *http.Request, name string) string { param := req.URL.Query().Get(name) @@ -446,8 +446,8 @@ func (c *RestService) GetParam(req *http.Request, name string) string { } // DecodeBody methods helps decode body -// - req - incoming request -// - target - pointer on target variable for decode +// - req - incoming request +// - target - pointer on target variable for decode // Returns error func (c *RestService) DecodeBody(req *http.Request, target interface{}) error { @@ -464,7 +464,7 @@ func (c *RestService) DecodeBody(req *http.Request, target interface{}) error { } // GetPagingParams methods helps decode paging params -// - req - incoming request +// - req - incoming request // Returns paging params func (c *RestService) GetPagingParams(req *http.Request) *cdata.PagingParams { @@ -477,7 +477,7 @@ func (c *RestService) GetPagingParams(req *http.Request) *cdata.PagingParams { } // GetFilterParams methods helps decode filter params -// - req - incoming request +// - req - incoming request // Returns filter params func (c *RestService) GetFilterParams(req *http.Request) *cdata.FilterParams { diff --git a/services/StatusOperations.go b/services/StatusOperations.go index 47d132a..06fb2a7 100644 --- a/services/StatusOperations.go +++ b/services/StatusOperations.go @@ -28,7 +28,7 @@ func NewStatusOperations() *StatusOperations { } // SetReferences sets references to dependent components. -// - references crefer.IReferences references to locate the component dependencies. +// - references crefer.IReferences references to locate the component dependencies. func (c *StatusOperations) SetReferences(references crefer.IReferences) { c.references2 = references c.RestOperations.SetReferences(references) @@ -47,8 +47,8 @@ func (c *StatusOperations) GetStatusOperation() func(res http.ResponseWriter, re } // Status method handles status requests -// - req *http.Request an HTTP request -// - res http.ResponseWriter an HTTP response +// - req *http.Request an HTTP request +// - res http.ResponseWriter an HTTP response func (c *StatusOperations) Status(res http.ResponseWriter, req *http.Request) { id := "" diff --git a/services/StatusRestService.go b/services/StatusRestService.go index da9d9f8..76eacb4 100644 --- a/services/StatusRestService.go +++ b/services/StatusRestService.go @@ -14,7 +14,7 @@ import ( StatusRestService is a service that returns microservice status information via HTTP/REST protocol. The service responds on /status route (can be changed) with a JSON object: -{ + { - "id": unique container id (usually hostname) - "name": container name (from ContextInfo) - "description": container description (from ContextInfo) @@ -23,21 +23,21 @@ The service responds on /status route (can be changed) with a JSON object: - "uptime": duration since container start time in milliseconds - "properties": additional container properties (from ContextInfo) - "components": descriptors of components registered in the container -} + } Configuration parameters: -- baseroute: base route for remote URI -- route: status route (default: "status") -- dependencies: - - endpoint: override for HTTP Endpoint dependency - - controller: override for Controller dependency -- connection(s): - - discovery_key: (optional) a key to retrieve the connection from IDiscovery - - protocol: connection protocol: http or https - - host: host name or IP address - - port: port number - - uri: resource URI or connection string with all parameters in it + - baseroute: base route for remote URI + - route: status route (default: "status") + - dependencies: + - endpoint: override for HTTP Endpoint dependency + - controller: override for Controller dependency + - connection(s): + - discovery_key: (optional) a key to retrieve the connection from IDiscovery + - protocol: connection protocol: http or https + - host: host name or IP address + - port: port number + - uri: resource URI or connection string with all parameters in it References: @@ -84,7 +84,7 @@ func NewStatusRestService() *StatusRestService { // Configure method are configures component by passing configuration parameters. // Parameters: -// - config *cconf.ConfigParams configuration parameters to be set. +// - config *cconf.ConfigParams configuration parameters to be set. func (c *StatusRestService) Configure(config *cconf.ConfigParams) { c.RestService.Configure(config) c.route = config.GetAsStringWithDefault("route", c.route) @@ -92,7 +92,7 @@ func (c *StatusRestService) Configure(config *cconf.ConfigParams) { // SetReferences method are sets references to dependent components. // Parameters: -// - references crefer.IReferences references to locate the component dependencies. +// - references crefer.IReferences references to locate the component dependencies. func (c *StatusRestService) SetReferences(references crefer.IReferences) { c.references2 = references c.RestService.SetReferences(references) @@ -109,8 +109,8 @@ func (c *StatusRestService) Register() { } // Handles status requests -// - req *http.Request an HTTP request -// - res http.ResponseWriter an HTTP response +// - req *http.Request an HTTP request +// - res http.ResponseWriter an HTTP response func (c *StatusRestService) status(res http.ResponseWriter, req *http.Request) { id := "" diff --git a/test.ps1 b/test.ps1 new file mode 100755 index 0000000..f00a964 --- /dev/null +++ b/test.ps1 @@ -0,0 +1,26 @@ +#!/usr/bin/env pwsh + +Set-StrictMode -Version latest +$ErrorActionPreference = "Stop" + +$component = Get-Content -Path "component.json" | ConvertFrom-Json +$testImage="$($component.registry)/$($component.name):$($component.version)-$($component.build)-test" + +# Set environment variables +$env:IMAGE = $testImage + +try { + # Workaround to remove dangling images + docker-compose -f ./docker/docker-compose.test.yml down + + docker-compose -f ./docker/docker-compose.test.yml up --build --abort-on-container-exit --exit-code-from test + + # Save the result to avoid overwriting it with the "down" command below + $exitCode = $LastExitCode +} finally { + # Workaround to remove dangling images + docker-compose -f ./docker/docker-compose.test.yml down +} + +# Return the exit code of the "docker-compose.test.yml up" command +exit $exitCode