From: Henrik Andersson Date: Wed, 15 Sep 2021 08:54:27 +0000 (+0000) Subject: Merge "Update pms image tag" X-Git-Tag: 1.2.0~88^2~1 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=7ea5ec4f81f6e8c07b890f3d7567ce699c8d8d1d;hp=0e23580adbdb4fbc116687ec1a3e07d35147a7b5;p=nonrtric.git Merge "Update pms image tag" --- diff --git a/dmaap-mediator-producer/.gitignore b/dmaap-mediator-producer/.gitignore new file mode 100644 index 00000000..567963e6 --- /dev/null +++ b/dmaap-mediator-producer/.gitignore @@ -0,0 +1,5 @@ +.history +.vscode +coverage.* +main +dmaapmediatorproducer diff --git a/dmaap-mediator-producer/Dockerfile b/dmaap-mediator-producer/Dockerfile new file mode 100644 index 00000000..95bcbae3 --- /dev/null +++ b/dmaap-mediator-producer/Dockerfile @@ -0,0 +1,39 @@ +#================================================================================== +# Copyright (C) 2021: Nordix Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This source code is part of the near-RT RIC (RAN Intelligent Controller) +# platform project (RICP). +#================================================================================== + +## +## Build +## +FROM golang:1.17-bullseye AS build +WORKDIR /app +COPY go.mod ./ +COPY go.sum ./ +RUN go mod download +COPY . ./ +RUN go build -o /dmaapmediatorproducer +## +## Deploy +## +FROM gcr.io/distroless/base-debian10 +WORKDIR / +## Copy from "build" stage +COPY --from=build /dmaapmediatorproducer . +COPY --from=build /app/configs/ configs +USER nonroot:nonroot +ENTRYPOINT ["/dmaapmediatorproducer"] diff --git a/dmaap-mediator-producer/build-dmaapmediatorproducer-ubuntu.sh b/dmaap-mediator-producer/build-dmaapmediatorproducer-ubuntu.sh new file mode 100755 index 00000000..ad8b8bb4 --- /dev/null +++ b/dmaap-mediator-producer/build-dmaapmediatorproducer-ubuntu.sh @@ -0,0 +1,35 @@ +#!/bin/bash +############################################################################## +# +# Copyright (C) 2021: Nordix Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +############################################################################## +set -eux + +echo "--> build-dmaapmediatorproducer-ubuntu.sh" +curdir=`pwd` +# go installs tools like go-acc to $HOME/go/bin +# ubuntu minion path lacks go +export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin + +# install the go coverage tool helper +go get -v github.com/ory/go-acc + +export GO111MODULE=on +go get github.com/stretchr/testify/mock@v1.7.0 + +go-acc ./... --ignore mocks + +echo "--> build-dmaapmediatorproducer-ubuntu.sh ends" diff --git a/dmaap-mediator-producer/configs/STD_Fault_Messages.json b/dmaap-mediator-producer/configs/STD_Fault_Messages.json new file mode 100644 index 00000000..b944802f --- /dev/null +++ b/dmaap-mediator-producer/configs/STD_Fault_Messages.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "STD_Fault_Messages", + "description": "Schema for job delivering fault messages from DMaaP Message Router", + "type": "object", + "properties": {} +} \ No newline at end of file diff --git a/dmaap-mediator-producer/container-tag.yaml b/dmaap-mediator-producer/container-tag.yaml new file mode 100644 index 00000000..230e5901 --- /dev/null +++ b/dmaap-mediator-producer/container-tag.yaml @@ -0,0 +1,2 @@ +--- +tag: 1.0.0 diff --git a/dmaap-mediator-producer/go.mod b/dmaap-mediator-producer/go.mod new file mode 100644 index 00000000..7e0d96ee --- /dev/null +++ b/dmaap-mediator-producer/go.mod @@ -0,0 +1,16 @@ +module oransc.org/nonrtric/dmaapmediatorproducer + +go 1.17 + +require ( + github.com/sirupsen/logrus v1.8.1 + github.com/stretchr/testify v1.7.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/objx v0.1.0 // indirect + golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 // indirect + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect +) diff --git a/dmaap-mediator-producer/go.sum b/dmaap-mediator-producer/go.sum new file mode 100644 index 00000000..2cf67a6d --- /dev/null +++ b/dmaap-mediator-producer/go.sum @@ -0,0 +1,18 @@ +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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/dmaap-mediator-producer/internal/config/config.go b/dmaap-mediator-producer/internal/config/config.go new file mode 100644 index 00000000..6969f9fa --- /dev/null +++ b/dmaap-mediator-producer/internal/config/config.go @@ -0,0 +1,47 @@ +// - +// ========================LICENSE_START================================= +// O-RAN-SC +// %% +// Copyright (C) 2021: Nordix Foundation +// %% +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ========================LICENSE_END=================================== +// + +package config + +import ( + "os" +) + +type Config struct { + LogLevel string + JobResultUri string + InfoCoordinatorAddress string +} + +func New() *Config { + return &Config{ + LogLevel: getEnv("LOG_LEVEL", "Info"), + JobResultUri: getEnv("JOB_RESULT_URI", ""), + InfoCoordinatorAddress: getEnv("INFO_COORD_ADDR", "http://enrichmentservice:8083"), + } +} + +func getEnv(key string, defaultVal string) string { + if value, exists := os.LookupEnv(key); exists { + return value + } + + return defaultVal +} diff --git a/dmaap-mediator-producer/internal/config/config_test.go b/dmaap-mediator-producer/internal/config/config_test.go new file mode 100644 index 00000000..f0106d0f --- /dev/null +++ b/dmaap-mediator-producer/internal/config/config_test.go @@ -0,0 +1,53 @@ +// - +// ========================LICENSE_START================================= +// O-RAN-SC +// %% +// Copyright (C) 2021: Nordix Foundation +// %% +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ========================LICENSE_END=================================== +// + +package config + +import ( + "os" + "reflect" + "testing" +) + +func TestNew_envVarsSetConfigContainSetValues(t *testing.T) { + os.Setenv("LOG_LEVEL", "Debug") + os.Setenv("JOB_RESULT_URI", "testUrl") + os.Setenv("INFO_COORD_ADDR", "testAddr") + defer os.Clearenv() + wantConfig := Config{ + LogLevel: "Debug", + JobResultUri: "testUrl", + InfoCoordinatorAddress: "testAddr", + } + if got := New(); !reflect.DeepEqual(got, &wantConfig) { + t.Errorf("New() = %v, want %v", got, &wantConfig) + } +} + +func TestNew_envVarsNotSetConfigContainDefaultValues(t *testing.T) { + wantConfig := Config{ + LogLevel: "Info", + JobResultUri: "", + InfoCoordinatorAddress: "http://enrichmentservice:8083", + } + if got := New(); !reflect.DeepEqual(got, &wantConfig) { + t.Errorf("New() = %v, want %v", got, &wantConfig) + } +} diff --git a/dmaap-mediator-producer/internal/config/registrator.go b/dmaap-mediator-producer/internal/config/registrator.go new file mode 100644 index 00000000..f846f9f5 --- /dev/null +++ b/dmaap-mediator-producer/internal/config/registrator.go @@ -0,0 +1,58 @@ +// - +// ========================LICENSE_START================================= +// O-RAN-SC +// %% +// Copyright (C) 2021: Nordix Foundation +// %% +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ========================LICENSE_END=================================== +// + +package config + +import ( + "fmt" + "net/url" + + log "github.com/sirupsen/logrus" + + "oransc.org/nonrtric/dmaapmediatorproducer/internal/jobtypes" + "oransc.org/nonrtric/dmaapmediatorproducer/internal/restclient" +) + +const registerTypePath = "/data-producer/v1/info-types/" + +type Registrator interface { + RegisterTypes(types []*jobtypes.Type) error +} + +type RegistratorImpl struct { + infoCoordinatorAddress string +} + +func NewRegistratorImpl(infoCoordAddr string) *RegistratorImpl { + return &RegistratorImpl{ + infoCoordinatorAddress: infoCoordAddr, + } +} + +func (r RegistratorImpl) RegisterTypes(jobTypes []*jobtypes.Type) error { + for _, jobType := range jobTypes { + body := fmt.Sprintf(`{"info_job_data_schema": %v}`, jobType.Schema) + if error := restclient.Put(r.infoCoordinatorAddress+registerTypePath+url.PathEscape(jobType.Name), []byte(body)); error != nil { + return error + } + log.Debugf("Registered type: %v", jobType) + } + return nil +} diff --git a/dmaap-mediator-producer/internal/config/registrator_test.go b/dmaap-mediator-producer/internal/config/registrator_test.go new file mode 100644 index 00000000..d3dd3a0c --- /dev/null +++ b/dmaap-mediator-producer/internal/config/registrator_test.go @@ -0,0 +1,70 @@ +// - +// ========================LICENSE_START================================= +// O-RAN-SC +// %% +// Copyright (C) 2021: Nordix Foundation +// %% +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ========================LICENSE_END=================================== +// + +package config + +import ( + "io/ioutil" + "net/http" + "testing" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "oransc.org/nonrtric/dmaapmediatorproducer/internal/jobtypes" + "oransc.org/nonrtric/dmaapmediatorproducer/internal/restclient" + "oransc.org/nonrtric/dmaapmediatorproducer/mocks" +) + +func TestRegisterTypes(t *testing.T) { + assertions := require.New(t) + + clientMock := mocks.HTTPClient{} + + clientMock.On("Do", mock.Anything).Return(&http.Response{ + StatusCode: http.StatusCreated, + }, nil) + + restclient.Client = &clientMock + + type1 := jobtypes.Type{ + Name: "Type1", + Schema: `{"title": "Type 1"}`, + } + types := []*jobtypes.Type{&type1} + + r := NewRegistratorImpl("http://localhost:9990") + err := r.RegisterTypes(types) + + assertions.Nil(err) + var actualRequest *http.Request + clientMock.AssertCalled(t, "Do", mock.MatchedBy(func(req *http.Request) bool { + actualRequest = req + return true + })) + assertions.Equal(http.MethodPut, actualRequest.Method) + assertions.Equal("http", actualRequest.URL.Scheme) + assertions.Equal("localhost:9990", actualRequest.URL.Host) + assertions.Equal("/data-producer/v1/info-types/Type1", actualRequest.URL.Path) + assertions.Equal("application/json; charset=utf-8", actualRequest.Header.Get("Content-Type")) + body, _ := ioutil.ReadAll(actualRequest.Body) + expectedBody := []byte(`{"info_job_data_schema": {"title": "Type 1"}}`) + assertions.Equal(expectedBody, body) + clientMock.AssertNumberOfCalls(t, "Do", 1) +} diff --git a/dmaap-mediator-producer/internal/jobtypes/jobtypes.go b/dmaap-mediator-producer/internal/jobtypes/jobtypes.go new file mode 100644 index 00000000..14d837de --- /dev/null +++ b/dmaap-mediator-producer/internal/jobtypes/jobtypes.go @@ -0,0 +1,68 @@ +// - +// ========================LICENSE_START================================= +// O-RAN-SC +// %% +// Copyright (C) 2021: Nordix Foundation +// %% +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ========================LICENSE_END=================================== +// + +package jobtypes + +import ( + "os" + "path/filepath" + "strings" +) + +type Type struct { + Name string + Schema string +} + +var typeDir = "configs" + +func GetTypes() ([]*Type, error) { + types := make([]*Type, 0, 1) + err := filepath.Walk(typeDir, + func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if strings.Contains(path, ".json") { + if jobType, err := getType(path); err == nil { + types = append(types, jobType) + } + } + return nil + }) + if err != nil { + return nil, err + } + return types, nil +} + +func getType(path string) (*Type, error) { + fileName := filepath.Base(path) + typeName := strings.TrimSuffix(fileName, filepath.Ext(fileName)) + + if typeSchema, err := os.ReadFile(path); err == nil { + return &Type{ + Name: typeName, + Schema: string(typeSchema), + }, nil + } else { + return nil, err + } +} diff --git a/dmaap-mediator-producer/internal/jobtypes/jobtypes_test.go b/dmaap-mediator-producer/internal/jobtypes/jobtypes_test.go new file mode 100644 index 00000000..5fdc378b --- /dev/null +++ b/dmaap-mediator-producer/internal/jobtypes/jobtypes_test.go @@ -0,0 +1,53 @@ +// - +// ========================LICENSE_START================================= +// O-RAN-SC +// %% +// Copyright (C) 2021: Nordix Foundation +// %% +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ========================LICENSE_END=================================== +// + +package jobtypes + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" +) + +const type1Schema = `{"title": "Type 1"}` + +func TestGetTypes_filesOkShouldReturnSliceOfTypes(t *testing.T) { + assertions := require.New(t) + typesDir, err := os.MkdirTemp("", "configs") + if err != nil { + t.Errorf("Unable to create temporary directory for types due to: %v", err) + } + defer os.RemoveAll(typesDir) + typeDir = typesDir + fname := filepath.Join(typesDir, "type1.json") + if err = os.WriteFile(fname, []byte(type1Schema), 0666); err != nil { + t.Errorf("Unable to create temporary files for types due to: %v", err) + } + types, err := GetTypes() + wantedType := Type{ + Name: "type1", + Schema: type1Schema, + } + wantedTypes := []*Type{&wantedType} + assertions.EqualValues(wantedTypes, types) + assertions.Nil(err) +} diff --git a/dmaap-mediator-producer/internal/restclient/HTTPClient.go b/dmaap-mediator-producer/internal/restclient/HTTPClient.go new file mode 100644 index 00000000..c6eb24c7 --- /dev/null +++ b/dmaap-mediator-producer/internal/restclient/HTTPClient.go @@ -0,0 +1,103 @@ +// - +// ========================LICENSE_START================================= +// O-RAN-SC +// %% +// Copyright (C) 2021: Nordix Foundation +// %% +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ========================LICENSE_END=================================== +// + +package restclient + +import ( + "bytes" + "fmt" + "io" + "net/http" +) + +// HTTPClient interface +type HTTPClient interface { + Get(url string) (*http.Response, error) + + Do(*http.Request) (*http.Response, error) +} + +type RequestError struct { + StatusCode int + Body []byte +} + +func (pe RequestError) Error() string { + return fmt.Sprintf("Request failed due to error response with status: %v and body: %v", pe.StatusCode, string(pe.Body)) +} + +var ( + Client HTTPClient +) + +func init() { + Client = &http.Client{} +} + +func Get(url string) ([]byte, error) { + if response, err := Client.Get(url); err == nil { + defer response.Body.Close() + if responseData, err := io.ReadAll(response.Body); err == nil { + if isResponseSuccess(response.StatusCode) { + return responseData, nil + } else { + requestError := RequestError{ + StatusCode: response.StatusCode, + Body: responseData, + } + return nil, requestError + } + } else { + return nil, err + } + } else { + return nil, err + } +} + +func Put(url string, body []byte) error { + if req, reqErr := http.NewRequest(http.MethodPut, url, bytes.NewBuffer(body)); reqErr == nil { + req.Header.Set("Content-Type", "application/json; charset=utf-8") + if response, respErr := Client.Do(req); respErr == nil { + if isResponseSuccess(response.StatusCode) { + return nil + } else { + return getRequestError(response) + } + } else { + return respErr + } + } else { + return reqErr + } +} + +func isResponseSuccess(statusCode int) bool { + return statusCode >= http.StatusOK && statusCode <= 299 +} + +func getRequestError(response *http.Response) RequestError { + responseData, _ := io.ReadAll(response.Body) + putError := RequestError{ + StatusCode: response.StatusCode, + Body: responseData, + } + return putError +} diff --git a/dmaap-mediator-producer/internal/restclient/HTTPClient_test.go b/dmaap-mediator-producer/internal/restclient/HTTPClient_test.go new file mode 100644 index 00000000..3727e6a3 --- /dev/null +++ b/dmaap-mediator-producer/internal/restclient/HTTPClient_test.go @@ -0,0 +1,164 @@ +// - +// ========================LICENSE_START================================= +// O-RAN-SC +// %% +// Copyright (C) 2021: Nordix Foundation +// %% +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ========================LICENSE_END=================================== +// + +package restclient + +import ( + "bytes" + "errors" + "io/ioutil" + "net/http" + "reflect" + "testing" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "oransc.org/nonrtric/dmaapmediatorproducer/mocks" +) + +func TestGet(t *testing.T) { + clientMock := mocks.HTTPClient{} + + clientMock.On("Get", "http://testOk").Return(&http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewReader([]byte("Response"))), + }, nil) + + clientMock.On("Get", "http://testNotOk").Return(&http.Response{ + StatusCode: http.StatusBadRequest, + Body: ioutil.NopCloser(bytes.NewReader([]byte("Bad Response"))), + }, nil) + + clientMock.On("Get", "http://testError").Return(nil, errors.New("Failed Request")) + + Client = &clientMock + + type args struct { + url string + } + tests := []struct { + name string + args args + want []byte + wantErr bool + wantedError error + }{ + { + name: "Test Get with OK response", + args: args{ + url: "http://testOk", + }, + want: []byte("Response"), + wantErr: false, + }, + { + name: "Test Get with Not OK response", + args: args{ + url: "http://testNotOk", + }, + want: nil, + wantErr: true, + wantedError: RequestError{ + StatusCode: http.StatusBadRequest, + Body: []byte("Bad Response"), + }, + }, + { + name: "Test Get with error", + args: args{ + url: "http://testError", + }, + want: nil, + wantErr: true, + wantedError: errors.New("Failed Request"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := Get(tt.args.url) + if (err != nil) != tt.wantErr { + t.Errorf("Get() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Get() = %v, want %v", got, tt.want) + } + if tt.wantErr && err.Error() != tt.wantedError.Error() { + t.Errorf("Get() error = %v, wantedError % v", err, tt.wantedError.Error()) + } + }) + } +} + +func TestPutOk(t *testing.T) { + assertions := require.New(t) + clientMock := mocks.HTTPClient{} + + clientMock.On("Do", mock.Anything).Return(&http.Response{ + StatusCode: http.StatusOK, + }, nil) + + Client = &clientMock + if err := Put("http://localhost:9990", []byte("body")); err != nil { + t.Errorf("Put() error = %v, did not want error", err) + } + var actualRequest *http.Request + clientMock.AssertCalled(t, "Do", mock.MatchedBy(func(req *http.Request) bool { + actualRequest = req + return true + })) + assertions.Equal(http.MethodPut, actualRequest.Method) + assertions.Equal("http", actualRequest.URL.Scheme) + assertions.Equal("localhost:9990", actualRequest.URL.Host) + assertions.Equal("application/json; charset=utf-8", actualRequest.Header.Get("Content-Type")) + body, _ := ioutil.ReadAll(actualRequest.Body) + expectedBody := []byte("body") + assertions.Equal(expectedBody, body) + clientMock.AssertNumberOfCalls(t, "Do", 1) +} + +func TestPutBadResponse(t *testing.T) { + assertions := require.New(t) + clientMock := mocks.HTTPClient{} + + clientMock.On("Do", mock.Anything).Return(&http.Response{ + StatusCode: http.StatusBadRequest, + Body: ioutil.NopCloser(bytes.NewReader([]byte("Bad Request"))), + }, nil) + + Client = &clientMock + err := Put("url", []byte("body")) + assertions.NotNil("Put() error = %v, wanted error", err) + expectedErrorMessage := "Request failed due to error response with status: 400 and body: Bad Request" + assertions.Equal(expectedErrorMessage, err.Error()) +} + +func TestPutError(t *testing.T) { + assertions := require.New(t) + clientMock := mocks.HTTPClient{} + + clientMock.On("Do", mock.Anything).Return(nil, errors.New("Failed Request")) + + Client = &clientMock + err := Put("url", []byte("body")) + assertions.NotNil("Put() error = %v, wanted error", err) + expectedErrorMessage := "Failed Request" + assertions.Equal(expectedErrorMessage, err.Error()) +} diff --git a/dmaap-mediator-producer/main.go b/dmaap-mediator-producer/main.go new file mode 100644 index 00000000..240bdbd5 --- /dev/null +++ b/dmaap-mediator-producer/main.go @@ -0,0 +1,59 @@ +// - +// ========================LICENSE_START================================= +// O-RAN-SC +// %% +// Copyright (C) 2021: Nordix Foundation +// %% +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ========================LICENSE_END=================================== +// + +package main + +import ( + "time" + + log "github.com/sirupsen/logrus" + "oransc.org/nonrtric/dmaapmediatorproducer/internal/config" + "oransc.org/nonrtric/dmaapmediatorproducer/internal/jobtypes" +) + +var configuration *config.Config + +func init() { + configuration = config.New() + if loglevel, err := log.ParseLevel(configuration.LogLevel); err == nil { + log.SetLevel(loglevel) + } else { + log.Warnf("Invalid log level: %v. Log level will be Info!", configuration.LogLevel) + } + + log.Debug("Initializing DMaaP Mediator Producer") + if configuration.JobResultUri == "" { + log.Fatal("Missing JOB_RESULT_URI") + } + + registrator := config.NewRegistratorImpl(configuration.InfoCoordinatorAddress) + if types, err := jobtypes.GetTypes(); err == nil { + if regErr := registrator.RegisterTypes(types); regErr != nil { + log.Fatalf("Unable to register all types due to: %v", regErr) + } + } else { + log.Fatalf("Unable to get types to register due to: %v", err) + } +} + +func main() { + log.Debug("Starting DMaaP Mediator Producer") + time.Sleep(1000 * time.Millisecond) +} diff --git a/dmaap-mediator-producer/mocks/HTTPClient.go b/dmaap-mediator-producer/mocks/HTTPClient.go new file mode 100644 index 00000000..3037798b --- /dev/null +++ b/dmaap-mediator-producer/mocks/HTTPClient.go @@ -0,0 +1,60 @@ +// Code generated by mockery v1.0.0. DO NOT EDIT. + +package mocks + +import ( + http "net/http" + + mock "github.com/stretchr/testify/mock" +) + +// HTTPClient is an autogenerated mock type for the HTTPClient type +type HTTPClient struct { + mock.Mock +} + +// Do provides a mock function with given fields: _a0 +func (_m *HTTPClient) Do(_a0 *http.Request) (*http.Response, error) { + ret := _m.Called(_a0) + + var r0 *http.Response + if rf, ok := ret.Get(0).(func(*http.Request) *http.Response); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*http.Response) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*http.Request) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Get provides a mock function with given fields: url +func (_m *HTTPClient) Get(url string) (*http.Response, error) { + ret := _m.Called(url) + + var r0 *http.Response + if rf, ok := ret.Get(0).(func(string) *http.Response); ok { + r0 = rf(url) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*http.Response) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(url) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} diff --git a/helm-manager/Dockerfile b/helm-manager/Dockerfile index 96a58319..90164fd7 100644 --- a/helm-manager/Dockerfile +++ b/helm-manager/Dockerfile @@ -15,21 +15,26 @@ # ============LICENSE_END================================================= # -FROM openjdk:11-jre-slim +FROM curlimages/curl:7.78.0 AS build + +#Get helm +RUN curl -Lo /tmp/helm.tar.gz https://get.helm.sh/helm-v3.6.1-linux-amd64.tar.gz + +#Get kubectl +RUN curl -Lo /tmp/kubectl https://dl.k8s.io/release/v1.20.2/bin/linux/amd64/kubectl -ARG JAR -#Install curl -RUN apt-get update && apt-get install -y curl \ - wget +FROM openjdk:11-jre-slim #Install helm -RUN wget -O helm.tar.gz https://get.helm.sh/helm-v3.6.1-linux-amd64.tar.gz +COPY --from=build /tmp/helm.tar.gz . + RUN tar -zxvf helm.tar.gz + RUN mv linux-amd64/helm /usr/local/bin/helm -#Install kubectl and configure -RUN curl -LO https://dl.k8s.io/release/v1.20.2/bin/linux/amd64/kubectl +#Install kubectl +COPY --from=build /tmp/kubectl . RUN chmod +x ./kubectl diff --git a/helm-manager/docker-hm.sh b/helm-manager/docker-hm.sh index c98b22a9..e51b5318 100755 --- a/helm-manager/docker-hm.sh +++ b/helm-manager/docker-hm.sh @@ -31,4 +31,4 @@ docker run \ -v ~/.cache/helm:/root/.cache/helm \ -v $(pwd)/config/KubernetesParticipantConfig.json:/opt/app/helm-manager/src/main/resources/config/KubernetesParticipantConfig.json \ -v $(pwd)/config/application.yaml:/opt/app/helm-manager/src/main/resources/config/application.yaml \ - nexus3.o-ran-sc.org:10004/o-ran-sc/nonrtric-helm-manager:1.0.0-SNAPSHOT \ No newline at end of file + nexus3.o-ran-sc.org:10004/o-ran-sc/nonrtric-helm-manager:1.1.0-SNAPSHOT diff --git a/helm-manager/helm-manager.yaml b/helm-manager/helm-manager.yaml index f372b301..5a3465c9 100644 --- a/helm-manager/helm-manager.yaml +++ b/helm-manager/helm-manager.yaml @@ -49,7 +49,7 @@ spec: serviceAccountName: helm-manager-sa containers: - name: helmmanagerservice - image: nexus3.o-ran-sc.org:10004/o-ran-sc/nonrtric-helm-manager:1.0.0 + image: nexus3.o-ran-sc.org:10004/o-ran-sc/nonrtric-helm-manager:1.1.0-SNAPSHOT imagePullPolicy: Always ports: - name: http