diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7796b7b..c15aeb0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,9 +4,13 @@
**Updates**
+* Ability to override Statistics->Resource in server.conf.yaml
* Improved the logging for metrics when authentication is not enabled
* Includes IT39515
* Includes IT39573
+* Includes IT39917
+* Remove need for python
+* Fix for CVE-2022-21698
## 12.0.3.0-r1
diff --git a/ace_config_setdbparms.sh b/ace_config_setdbparms.sh
index b524dfa..0c40dda 100755
--- a/ace_config_setdbparms.sh
+++ b/ace_config_setdbparms.sh
@@ -7,21 +7,6 @@
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v20.html
-function argStrings {
- shlex() {
- python -c $'import sys, shlex\nfor arg in shlex.split(sys.stdin):\n\tsys.stdout.write(arg)\n\tsys.stdout.write(\"\\0\")'
- }
- args=()
- while IFS='' read -r -d ''; do
- args+=( "$REPLY" )
- done < <(shlex <<<$1)
-
- log "${args[0]}"
- log "${args[1]}"
- log "${args[2]}"
-
-}
-
if [ -z "$MQSI_VERSION" ]; then
source /opt/ibm/ace-12/server/bin/mqsiprofile
fi
@@ -41,19 +26,17 @@ if [ -s "/home/aceuser/initial-config/setdbparms/setdbparms.txt" ]; then
continue
fi
IFS=${OLDIFS}
- if [[ $line == mqsisetdbparms* ]]; then
+ if [[ $line == mqsisetdbparms* ]]; then
log "Running suppplied mqsisetdbparms command"
OUTPUT=`eval "$line"`
else
- shlex() {
- python -c $'import sys, shlex\nfor arg in shlex.split(sys.stdin):\n\tsys.stdout.write(arg)\n\tsys.stdout.write(\"\\0\")'
- }
- args=()
- while IFS='' read -r -d ''; do
- args+=( "$REPLY" )
- done < <(shlex <<<$line)
- log "Setting user and password for resource: ${args[0]}"
- cmd="mqsisetdbparms -w /home/aceuser/ace-server -n \"${args[0]}\" -u \"${args[1]}\" -p \"${args[2]}\" 2>&1"
+
+ printf "%s" "$line" | xargs -n 1 printf "%s\n" > /tmp/creds
+ IFS=$'\n' read -d '' -r -a lines < /tmp/creds
+
+
+ log "Setting user and password for resource: ${lines[0]}"
+ cmd="mqsisetdbparms -w /home/aceuser/ace-server -n \"${lines[0]}\" -u \"${lines[1]}\" -p \"${lines[2]}\" 2>&1"
OUTPUT=`eval "$cmd"`
echo $OUTPUT
fi
diff --git a/cmd/chkacehealthy/.gitignore b/cmd/chkacehealthy/.gitignore
new file mode 100644
index 0000000..1349ec4
--- /dev/null
+++ b/cmd/chkacehealthy/.gitignore
@@ -0,0 +1 @@
+chkacehealthy
\ No newline at end of file
diff --git a/cmd/chkacehealthy/main.go b/cmd/chkacehealthy/main.go
index 4735c53..987633e 100644
--- a/cmd/chkacehealthy/main.go
+++ b/cmd/chkacehealthy/main.go
@@ -18,17 +18,97 @@ limitations under the License.
package main
import (
+ "context"
"fmt"
+ "log"
"net"
+ "net/http"
"os"
"time"
+
+ "k8s.io/apimachinery/pkg/api/errors"
)
+var checkACE = checkACElocal
+var httpCheck = httpChecklocal
+var socketCheck = socketChecklocal
+var osExit = os.Exit
+
const restartIsTimeoutInSeconds = 60
+var netDial = net.Dial
+var httpGet = http.Get
+
func main() {
+
+ err := checkACE()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // If knative service also check FDR is up
+ knative := os.Getenv("KNATIVESERVICE")
+ if knative == "true" || knative == "1" {
+ fmt.Println("KNATIVESERVICE set so checking FDR container")
+ err := checkDesignerHealth()
+ if err != nil {
+ log.Fatal(err)
+ }
+ } else {
+ fmt.Println("KNATIVESERVICE is not set so skipping FDR checks")
+ }
+
+}
+
+func checkDesignerHealth() error {
+ // HTTP LMAP endpoint
+ err := httpCheck("LMAP Port", "http://localhost:3002/admin/ready")
+ if err != nil {
+ return err
+ }
+
+ isConnectorService := os.Getenv("CONNECTOR_SERVICE")
+ if isConnectorService == "true" || isConnectorService == "1" {
+ // HTTP LCP Connector service endpoint
+ err = httpCheck("LCP Port", "http://localhost:3001/admin/ready")
+ if err != nil {
+ return err
+ }
+ }
+
+ // LCP api flow endpoint
+ lcpsocket := "/tmp/lcp.socket"
+ if value, ok := os.LookupEnv("LCP_IPC_PATH"); ok {
+ lcpsocket = value
+ }
+ err = socketCheck("LCP socket", lcpsocket)
+ if err != nil {
+ return err
+ }
+
+ // LMAP endpoint
+ lmapsocket := "/tmp/lmap.socket"
+ if value, ok := os.LookupEnv("LMAP_IPC_PATH"); ok {
+ lmapsocket = value
+ }
+ err = socketCheck("LMAP socket", lmapsocket)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func isEnvExist(key string) bool {
+ if _, ok := os.LookupEnv(key); ok {
+ return true
+ }
+ return false
+}
+
+func checkACElocal() error {
// Check if the integration server has started the admin REST endpoint
- conn, err := net.Dial("tcp", "127.0.0.1:7600")
+ conn, err := netDial("tcp", "127.0.0.1:7600")
if err != nil {
@@ -38,10 +118,10 @@ func main() {
if os.IsNotExist(statErr) {
fmt.Println("Integration server is not active")
- os.Exit(1)
- } else if statErr != nil {
+ return errors.NewBadRequest("Integration server is not active")
+ } else if statErr != nil {
fmt.Println(statErr)
- os.Exit(1)
+ return errors.NewBadRequest("stat error " + statErr.Error())
} else {
fmt.Println("Integration server restart file found")
timeNow := time.Now()
@@ -49,13 +129,49 @@ func main() {
if timeDiff.Seconds() < restartIsTimeoutInSeconds {
fmt.Println("Integration server is restarting")
- os.Exit(0)
} else {
fmt.Println("Integration restart time elapsed")
- os.Exit(1)
+ return errors.NewBadRequest("Integration restart time elapsed")
}
}
+ } else {
+ fmt.Println("ACE ready check passed")
}
conn.Close()
+ return nil
+}
+
+func httpChecklocal(name string, addr string) error {
+ resp, err := httpGet(addr)
+ if err != nil {
+ return err
+ }
+ if resp.StatusCode != 200 {
+ fmt.Println(name + " ready check failed - HTTP Status is not 200 range")
+ return errors.NewBadRequest(name + " ready check failed - HTTP Status is not 200 range")
+ } else {
+ fmt.Println(name + " ready check passed")
+ }
+ return nil
+}
+func socketChecklocal(name string, socket string) error {
+ httpc := http.Client{
+ Transport: &http.Transport{
+ DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
+ return net.Dial("unix", socket)
+ },
+ },
+ }
+ response, err := httpc.Get("http://dummyHostname/admin/ready")
+ if err != nil {
+ return err
+ }
+ if response.StatusCode != 200 {
+ log.Fatal(name + " ready check failed - HTTP Status is not 200 range")
+ return errors.NewBadRequest(name + " ready check failed - HTTP Status is not 200 range")
+ } else {
+ fmt.Println(name + " ready check passed")
+ }
+ return nil
}
diff --git a/cmd/chkacehealthy/main_test.go b/cmd/chkacehealthy/main_test.go
new file mode 100644
index 0000000..4406566
--- /dev/null
+++ b/cmd/chkacehealthy/main_test.go
@@ -0,0 +1,134 @@
+/*
+© Copyright IBM Corporation 2018
+
+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.
+*/
+
+// chkacelively checks that ACE is still runing, by checking if the admin REST endpoint port is available.
+package main
+
+import (
+ "net/http"
+ "os"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "k8s.io/apimachinery/pkg/api/errors"
+)
+
+func Test_httpChecklocal(t *testing.T) {
+
+ t.Run("http get succeeds", func(t *testing.T) {
+
+ oldhttpGet := httpGet
+ defer func() { httpGet = oldhttpGet }()
+ httpGet = func(string) (resp *http.Response, err error) {
+ response := &http.Response{
+ StatusCode: 200,
+ }
+ return response, nil
+ }
+
+ err := httpChecklocal("LMAP Port", "http://localhost:3002/admin/ready")
+ assert.Nil(t, err)
+ })
+
+ t.Run("http get fails with err on get", func(t *testing.T) {
+
+ oldhttpGet := httpGet
+ defer func() { httpGet = oldhttpGet }()
+ httpGet = func(string) (resp *http.Response, err error) {
+ response := &http.Response{}
+ return response, errors.NewBadRequest("mock err")
+ }
+
+ err := httpChecklocal("LMAP Port", "http://localhost:3002/admin/ready")
+ assert.Error(t, err, "mock err")
+ })
+
+ t.Run("http get fails with non 200", func(t *testing.T) {
+
+ oldhttpGet := httpGet
+ defer func() { httpGet = oldhttpGet }()
+ httpGet = func(string) (resp *http.Response, err error) {
+ response := &http.Response{
+ StatusCode: 404,
+ }
+ return response, nil
+ }
+
+ err := httpChecklocal("Test", "http://localhost:3002/admin/ready")
+ assert.Error(t, err, "Test ready check failed - HTTP Status is not 200 range")
+ })
+}
+
+func Test_checkDesignerHealth(t *testing.T) {
+ t.Run("connector service enabled and health check is successful", func(t *testing.T) {
+ os.Setenv("CONNECTOR_SERVICE", "true")
+ defer os.Unsetenv("CONNECTOR_SERVICE")
+ oldhttpGet := httpGet
+ defer func() { httpGet = oldhttpGet }()
+ httpGet = func(string) (resp *http.Response, err error) {
+ response := &http.Response{
+ StatusCode: 200,
+ }
+ return response, nil
+ }
+
+ oldSocketCheck := socketCheck
+ defer func() { socketCheck = oldSocketCheck }()
+ socketCheck = func(string, string) (err error) {
+ return nil
+ }
+ err := checkDesignerHealth()
+ assert.Nil(t, err)
+ })
+
+ t.Run("connector service enabled and health check fails", func(t *testing.T) {
+ os.Setenv("CONNECTOR_SERVICE", "true")
+ defer os.Unsetenv("CONNECTOR_SERVICE")
+ oldhttpGet := httpGet
+ defer func() { httpGet = oldhttpGet }()
+ httpGet = func(string) (resp *http.Response, err error) {
+ response := &http.Response{}
+ return response, errors.NewBadRequest("mock err")
+ }
+
+ oldSocketCheck := socketCheck
+ defer func() { socketCheck = oldSocketCheck }()
+ socketCheck = func(string, string) (err error) {
+ return nil
+ }
+ err := checkDesignerHealth()
+ assert.Error(t, err, "mock err")
+ })
+
+ t.Run("health check fails for socket http server", func(t *testing.T) {
+ oldhttpGet := httpGet
+ defer func() { httpGet = oldhttpGet }()
+ httpGet = func(string) (resp *http.Response, err error) {
+ response := &http.Response{
+ StatusCode: 200,
+ }
+ return response, nil
+ }
+
+ oldSocketCheck := socketCheck
+ defer func() { socketCheck = oldSocketCheck }()
+ socketCheck = func(string, string) (err error) {
+ return errors.NewBadRequest("mock err")
+ }
+ err := checkDesignerHealth()
+ assert.Error(t, err, "mock err")
+ })
+}
diff --git a/cmd/runaceserver/integrationserver.go b/cmd/runaceserver/integrationserver.go
index 232a8aa..e2da12c 100644
--- a/cmd/runaceserver/integrationserver.go
+++ b/cmd/runaceserver/integrationserver.go
@@ -64,6 +64,9 @@ var yamlUnmarshal = yaml.Unmarshal
var yamlMarshal = yaml.Marshal
var writeServerConfFile = writeServerConfFileLocal
var getConfigurationFromContentServer = getConfigurationFromContentServerLocal
+var commandRunCmd = command.RunCmd
+var packageBarFile = packageBarFileLocal
+var deployBarFile = deployBarFileLocal
// initialIntegrationServerConfig walks through the /home/aceuser/initial-config directory
// looking for directories (each containing some config data), then runs a shell script
@@ -122,7 +125,10 @@ func initialIntegrationServerConfig() error {
return err
}
}
- if file.Name() != "webusers" {
+
+ // do not generate script for webusers dir or designerflowyaml
+ // designerflowyaml is where we mount the ConfigMaps containing the IntegrationFlow resources
+ if file.Name() != "webusers" && file.Name() != "designerflowyaml" && file.Name() != "generated-bar" {
cmd := exec.Command("ace_config_" + file.Name() + ".sh")
out, _, err := command.RunCmd(cmd)
if err != nil {
@@ -198,6 +204,17 @@ func initialIntegrationServerConfig() error {
log.Printf("Not Forcing all flows to be https as FORCE_FLOW_HTTPS=%v", forceFlowHttps)
}
+ isEnabled, checkGlobalCacheError := checkGlobalCacheConfigurations()
+ if checkGlobalCacheError != nil {
+ log.Errorf("Error checking global cache configurations in server.conf.yaml: %v", checkGlobalCacheError)
+ return checkGlobalCacheError
+ }
+ if isEnabled {
+ log.Printf("*******")
+ log.Printf("The embedded global cache is enabled. This configuration is not supported in a containerized environment. For more information, see https://ibm.biz/aceglobalcache.")
+ log.Printf("*******")
+ }
+
log.Println("Initial configuration of integration server complete")
return nil
@@ -408,7 +425,14 @@ func addMetricsToServerConf(serverconfContent []byte) ([]byte, error) {
statistics["Snapshot"] = snapshotObj
}
- statistics["Resource"] = resourceObj
+ if statistics["Resource"] != nil {
+ resource := statistics["Resource"].(map[interface{}]interface{})
+ if resource["reportingOn"] == nil {
+ resource["reportingOn"] = true
+ }
+ } else {
+ statistics["Resource"] = resourceObj
+ }
} else {
serverconfMap["Statistics"] = map[string]interface{}{
@@ -443,7 +467,7 @@ func addOpenTracingToServerConf(serverconfContent []byte) ([]byte, error) {
userExits["userExitPath"] = "/opt/ACEOpenTracing"
} else {
- serverconfMap["UserExits"] = map[interface{}]interface{} {
+ serverconfMap["UserExits"] = map[interface{}]interface{}{
"activeUserExitList": "ACEOpenTracingUserExit",
"userExitPath": "/opt/ACEOpenTracing",
}
@@ -712,7 +736,12 @@ func waitForIntegrationServer() error {
cmd := exec.Command("chkaceready")
_, rc, err := command.RunCmd(cmd)
if rc != 0 || err != nil {
- log.Printf("Integration server not ready yet")
+ knative := os.Getenv("KNATIVESERVICE")
+ if knative == "true" || knative == "1" {
+ log.Printf("Integration server & FDR not ready yet")
+ } else {
+ log.Printf("Integration server not ready yet")
+ }
}
if rc == 0 {
break
@@ -730,15 +759,45 @@ func stopIntegrationServer(integrationServerProcess command.BackgroundCmd) {
}
func createWorkDir() error {
- log.Printf("Attempting to initialise /home/aceuser/ace-server")
- cmd := exec.Command("/opt/ibm/ace-12/server/bin/mqsicreateworkdir", "/home/aceuser/ace-server")
+ if _, err := os.Stat("/home/aceuser/ace-server/server.conf.yaml"); errors.Is(err, os.ErrNotExist) {
+ log.Printf("Attempting to initialise /home/aceuser/ace-server")
+
+ // Run mqsicreateworkdir code
+ cmd := exec.Command("/opt/ibm/ace-12/server/bin/mqsicreateworkdir", "/home/aceuser/ace-server")
+ _, _, err := command.RunCmd(cmd)
+ if err != nil {
+ log.Printf("Error initializing work dir")
+ return err
+ }
+ log.Printf("Work dir initialization complete")
+ } else {
+ log.Printf("/home/aceuser/ace-server/server.conf.yaml found, not initializing Work dir")
+ }
+ return nil
+}
+
+func createWorkDirSymLink() error {
+ log.Printf("Attempting to move / symlink /home/aceuser/ace-server to shared mount")
+ cmd := exec.Command("cp", "-r", "/home/aceuser/ace-server", "/workdir-shared/")
_, _, err := command.RunCmd(cmd)
if err != nil {
- log.Printf("Error initializing work dir")
+ log.Printf("Error copying workdir to shared work dir")
+ return err
+ }
+ cmd = exec.Command("rm", "-rf", "/home/aceuser/ace-server")
+ _, _, err = command.RunCmd(cmd)
+ if err != nil {
+ log.Printf("Error deleting original work dir")
+ return err
+ }
+ cmd = exec.Command("ln", "-s", "/workdir-shared/ace-server", "/home/aceuser/")
+ _, _, err = command.RunCmd(cmd)
+ if err != nil {
+ log.Printf("Error creating symlink")
return err
}
-
- log.Printf("Work dir initialization complete")
+
+ log.Printf("Work dir symlink complete")
return nil
}
@@ -905,6 +964,37 @@ func addforceFlowsHttpsToServerConf(serverconfContent []byte) ([]byte, error) {
return serverconfYaml, nil
}
+func checkGlobalCacheConfigurations() (bool, error) {
+ isEmbeddedCacheEnabled := false
+ serverconfContent, readError := readServerConfFile()
+ if readError != nil {
+ if !os.IsNotExist(readError) {
+ // Error is different from file not existing (if the file does not exist we will create it ourselves)
+ log.Errorf("Error reading server.conf.yaml: %v", readError)
+ return isEmbeddedCacheEnabled, readError
+ }
+ }
+
+ serverconfMap := make(map[interface{}]interface{})
+ unmarshallError := yaml.Unmarshal([]byte(serverconfContent), &serverconfMap)
+ if unmarshallError != nil {
+ log.Errorf("Error unmarshalling server.conf.yaml: %v", unmarshallError)
+ return isEmbeddedCacheEnabled, unmarshallError
+ }
+
+ if serverconfMap["ResourceManagers"] != nil {
+ resourceManagers := serverconfMap["ResourceManagers"].(map[interface{}]interface{})
+ if resourceManagers["GlobalCache"] != nil {
+ globalCache := resourceManagers["GlobalCache"].(map[interface{}]interface{})
+ if globalCache["cacheOn"] == true && globalCache["enableCatalogService"] == true && globalCache["enableContainerService"] == true {
+ isEmbeddedCacheEnabled = true
+ }
+ }
+ }
+
+ return isEmbeddedCacheEnabled, nil
+}
+
func generatePassword(length int64) string {
var i, e = big.NewInt(length), big.NewInt(10)
bigInt, _ := rand.Int(rand.Reader, i.Exp(e, i, nil))
@@ -1035,4 +1125,106 @@ func localPatchHTTPSConnector(uds string) {
} else {
log.Println("Call made to restart HTTPSConnector for Force Flows HTTPS")
}
+
}
+
+func deployIntegrationFlowResources() error {
+ log.Println("Deploying IntegrationFlow resources")
+ err := packageBarFile()
+ if err != nil {
+ log.Println(err)
+ return err
+ }
+
+ err = deployBarFile()
+ if err != nil {
+ log.Println(err)
+ return err
+ }
+
+ return nil
+}
+
+func packageBarFileLocal() error {
+ cmd := exec.Command("/opt/ibm/ace-12/common/node/bin/node", "/opt/ibm/acecc-bar-gen/acecc-bar-gen.js", "2>&1")
+ out, _, err := commandRunCmd(cmd)
+ if err != nil {
+ log.Println("Error packaging BAR file :", err)
+ return err
+ }
+ log.Print(out)
+
+ return nil
+}
+
+func deployBarFileLocal() error {
+ mqsiCommand := exec.Command("/bin/sh", "-c", "source /opt/ibm/ace-12/server/bin/mqsiprofile; /opt/ibm/ace-12/server/bin/ibmint deploy --input-bar-file /home/aceuser/initial-config/generated-bar/integrationFlowResources.bar --output-work-directory /home/aceuser/ace-server")
+ out, _, err := commandRunCmd(mqsiCommand)
+ if err != nil {
+ fmt.Println("Error deploying BAR file :", err)
+ return err
+ }
+ log.Print(out)
+ return nil
+}
+
+func deployCSAPIFlows() error {
+ csAPIProxy := os.Getenv("CONNECTOR_SERVICE")
+ if csAPIProxy == "true" || csAPIProxy == "1" {
+ log.Println("Deploying Connector Service API Proxy Flow")
+ cpCommand := exec.Command("cp", "--recursive", "/home/aceuser/deps/CSAPI", "/home/aceuser/ace-server/run/CSAPI")
+ out, _, err := commandRunCmd(cpCommand)
+ if err != nil {
+ log.Println("Error deploying copy CS API flow files :", err)
+ return err
+ }
+ log.Print(out)
+ log.Println("Connector Service API flow deployed")
+ }
+ return nil
+}
+
+// This function updates the server.conf.yaml with the fields required to
+// force basic auth on all flows
+func forceflowbasicauthServerConfUpdate() error {
+
+ log.Println("Enabling basic auth on all flows in server.conf.yaml")
+
+ serverconfContent, readError := readServerConfFile()
+ if readError != nil {
+ if !os.IsNotExist(readError) {
+ // Error is different from file not existing (if the file does not exist we will create it ourselves)
+ log.Errorf("Error reading server.conf.yaml: %v", readError)
+ return readError
+ }
+ }
+
+ serverconfMap := make(map[interface{}]interface{})
+ unmarshallError := yamlUnmarshal([]byte(serverconfContent), &serverconfMap)
+ if unmarshallError != nil {
+ log.Errorf("Error unmarshalling server.conf.yaml: %v", unmarshallError)
+ return unmarshallError
+ }
+
+ if serverconfMap["forceServerHTTPSecurityProfile"] == nil {
+ serverconfMap["forceServerHTTPSecurityProfile"] = "{DefaultPolicies}:SecProfLocal"
+ } else {
+ log.Println("WARNING: You have asked to force basic auth on all flows but already have forceServerHTTPSecurityProfile set")
+ log.Println("WARNING: We will not override this existing value which may prevent the basic working. ")
+ }
+
+ serverconfYaml, marshallError := yamlMarshal(&serverconfMap)
+ if marshallError != nil {
+ log.Errorf("Error marshalling server.conf.yaml: %v", marshallError)
+ return marshallError
+ }
+
+ writeError := writeServerConfFile(serverconfYaml)
+ if writeError != nil {
+ return writeError
+ }
+
+ log.Println("forceServerHTTPSecurityProfile enabled in server.conf.yaml")
+
+ return nil
+}
\ No newline at end of file
diff --git a/cmd/runaceserver/integrationserver_internal_test.go b/cmd/runaceserver/integrationserver_internal_test.go
index 54ed559..1d02e01 100644
--- a/cmd/runaceserver/integrationserver_internal_test.go
+++ b/cmd/runaceserver/integrationserver_internal_test.go
@@ -131,6 +131,35 @@ Statistics:
publicationOn: mockValue3
threadDataLevel: mockValue4
`},
+{ // User's yaml has accountingOrigin in Statistics.Snapshot and overriden outputFormat. It keeps these values.
+`
+Statistics:
+ Resource:
+ outputFormat: file`,
+`Statistics:
+ Resource:
+ outputFormat: file
+ reportingOn: true
+ Snapshot:
+ accountingOrigin: none
+ nodeDataLevel: basic
+ outputFormat: json
+ publicationOn: active
+ threadDataLevel: none
+`},
+{ // User's yaml has bare minimum. Our defaults added.
+`
+Statistics:`,
+`Statistics:
+ Resource:
+ reportingOn: true
+ Snapshot:
+ accountingOrigin: none
+ nodeDataLevel: basic
+ outputFormat: json
+ publicationOn: active
+ threadDataLevel: none
+`},
}
func TestAddMetricsToServerConf(t *testing.T) {
@@ -356,6 +385,70 @@ func TestAddforceFlowsHttpsToServerConf(t *testing.T) {
}
}
+func TestCheckGlobalCacheConfigurations(t *testing.T) {
+ t.Run("When global cache is not configured, no warning message is issued.", func(t *testing.T) {
+ serverConfigYaml := `ResourceManagers:`
+
+ readServerConfFile = func() ([]byte, error) {
+ return []byte(serverConfigYaml), nil
+ }
+
+ isEmbeddedCacheEnabled, err := checkGlobalCacheConfigurations()
+ assert.NoError(t, err)
+ assert.Equal(t, isEmbeddedCacheEnabled, false, "The WXS server should be disabled.")
+ })
+
+ t.Run("When global cache is disabled, no warning message is issued.", func(t *testing.T) {
+ serverConfigYaml :=
+`ResourceManagers:
+ GlobalCache:
+ cacheOn: false
+ enableCatalogService: false
+ enableContainerService: false`
+
+ readServerConfFile = func() ([]byte, error) {
+ return []byte(serverConfigYaml), nil
+ }
+
+ isEmbeddedCacheEnabled, err := checkGlobalCacheConfigurations()
+ assert.NoError(t, err)
+ assert.Equal(t, isEmbeddedCacheEnabled, false, "The WXS server should be disabled.")
+ })
+
+ t.Run("When global cache is enabled without the WXS server, no warning message is issued.", func(t *testing.T) {
+ serverConfigYaml :=
+`ResourceManagers:
+ GlobalCache:
+ cacheOn: true
+ enableCatalogService: false
+ enableContainerService: false`
+
+ readServerConfFile = func() ([]byte, error) {
+ return []byte(serverConfigYaml), nil
+ }
+
+ isEmbeddedCacheEnabled, err := checkGlobalCacheConfigurations()
+ assert.NoError(t, err)
+ assert.Equal(t, isEmbeddedCacheEnabled, false, "The WXS server should be disabled.")
+ })
+
+ t.Run("When both global cache and the WXS server are enabled, a warning message is issued.", func(t *testing.T) {
+ serverConfigYaml :=
+`ResourceManagers:
+ GlobalCache:
+ cacheOn: true
+ enableCatalogService: true
+ enableContainerService: true`
+
+ readServerConfFile = func() ([]byte, error) {
+ return []byte(serverConfigYaml), nil
+ }
+
+ isEmbeddedCacheEnabled, err := checkGlobalCacheConfigurations()
+ assert.NoError(t, err)
+ assert.Equal(t, isEmbeddedCacheEnabled, true, "The WXS server should be enabled.")
+ })
+}
func TestGetConfigurationFromContentServer(t *testing.T) {
diff --git a/cmd/runaceserver/integrationserver_test.go b/cmd/runaceserver/integrationserver_test.go
index a8afb58..98b4fe5 100644
--- a/cmd/runaceserver/integrationserver_test.go
+++ b/cmd/runaceserver/integrationserver_test.go
@@ -3,10 +3,12 @@ package main
import (
"errors"
"os"
+ "os/exec"
"testing"
"github.com/ot4i/ace-docker/common/logger"
"github.com/stretchr/testify/assert"
+ "gopkg.in/yaml.v2"
)
func Test_initialIntegrationServerConfig(t *testing.T) {
@@ -171,3 +173,266 @@ func Test_createSHAServerConfYamlLocal(t *testing.T) {
writeServerConfFile = oldWriteServerConfFile
})
}
+
+func Test_deployIntegrationFlowResources(t *testing.T) {
+ t.Run("deployIntegrationFlowResources returns nil as both commands returned without error", func(t *testing.T) {
+ oldcommandRunCmd := commandRunCmd
+ defer func() { commandRunCmd = oldcommandRunCmd }()
+ commandRunCmd = func(cmd *exec.Cmd) (string, int, error) {
+ return "success", 0, nil
+ }
+ err := deployIntegrationFlowResources()
+ assert.NoError(t, err)
+ })
+
+ t.Run("deployIntegrationFlowResources error running acecc-bar-gen.js", func(t *testing.T) {
+ oldpackageBarFile := packageBarFile
+ defer func() { packageBarFile = oldpackageBarFile }()
+ packageBarFile = func() error {
+ err := errors.New("Error running acecc-bar-gen.js")
+ return err
+ }
+
+ oldcommandRunCmd := commandRunCmd
+ defer func() { commandRunCmd = oldcommandRunCmd }()
+ commandRunCmd = func(cmd *exec.Cmd) (string, int, error) {
+ err := errors.New("Error running acecc-bar-gen.js")
+ return "Error running acecc-bar-gen.js", 1, err
+ }
+
+ err := deployIntegrationFlowResources()
+ assert.Error(t, err)
+ })
+
+ t.Run("deployIntegrationFlowResources error deploying BAR file - non zero return code", func(t *testing.T) {
+ oldpackageBarFile := packageBarFile
+ defer func() { packageBarFile = oldpackageBarFile }()
+ packageBarFile = func() error {
+ return nil
+ }
+
+ olddeployBarFile := deployBarFile
+ defer func() { deployBarFile = olddeployBarFile }()
+ deployBarFile = func() error {
+ err := errors.New("Error deploying BAR file")
+ return err
+ }
+ oldcommandRunCmd := commandRunCmd
+ defer func() { commandRunCmd = oldcommandRunCmd }()
+ commandRunCmd = func(cmd *exec.Cmd) (string, int, error) {
+ err := errors.New("Error deploying BAR file")
+ return "Error deploying BAR file", 1, err
+ }
+
+ err := deployIntegrationFlowResources()
+ assert.Error(t, err)
+ })
+}
+
+func Test_PackageBarFile(t *testing.T) {
+ t.Run("Success running acecc-bar-gen.js", func(t *testing.T) {
+
+ oldcommandRunCmd := commandRunCmd
+ defer func() { commandRunCmd = oldcommandRunCmd }()
+ commandRunCmd = func(cmd *exec.Cmd) (string, int, error) {
+ return "Success", 0, nil
+ }
+ err := packageBarFile()
+ assert.NoError(t, err)
+
+ })
+ t.Run("Error running acecc-bar-gen.js", func(t *testing.T) {
+
+ oldcommandRunCmd := commandRunCmd
+ defer func() { commandRunCmd = oldcommandRunCmd }()
+ commandRunCmd = func(cmd *exec.Cmd) (string, int, error) {
+ err := errors.New("Error running acecc-bar-gen.js")
+ return "Error running acecc-bar-gen.js", 1, err
+ }
+ err := packageBarFile()
+ assert.Error(t, err)
+ })
+}
+
+func Test_DeployBarFile(t *testing.T) {
+ t.Run("Success deploying BAR file", func(t *testing.T) {
+ oldcommandRunCmd := commandRunCmd
+ defer func() { commandRunCmd = oldcommandRunCmd }()
+ commandRunCmd = func(cmd *exec.Cmd) (string, int, error) {
+ return "Success", 0, nil
+ }
+ err := deployBarFile()
+ assert.NoError(t, err)
+
+ })
+ t.Run("Error deploying BAR file", func(t *testing.T) {
+ oldcommandRunCmd := commandRunCmd
+ defer func() { commandRunCmd = oldcommandRunCmd }()
+ commandRunCmd = func(cmd *exec.Cmd) (string, int, error) {
+ err := errors.New("Error running deploying BAR file")
+ return "Error running deploying BAR file", 1, err
+ }
+ err := deployBarFile()
+ assert.Error(t, err)
+ })
+
+}
+
+func Test_deployCSAPIFlows(t *testing.T) {
+
+ t.Run("Env var not set", func(t *testing.T) {
+ called := 0
+ oldcommandRunCmd := commandRunCmd
+ defer func() { commandRunCmd = oldcommandRunCmd }()
+ commandRunCmd = func(cmd *exec.Cmd) (string, int, error) {
+ called++
+ return "Success", 0, nil
+ }
+ err := deployCSAPIFlows()
+ assert.NoError(t, err)
+ assert.Equal(t, 0, called)
+ })
+
+ t.Run("Env var not set", func(t *testing.T) {
+ os.Setenv("CONNECTOR_SERVICE", "true")
+
+ t.Run("Success deploying copyied files", func(t *testing.T) {
+ var command []string
+ oldcommandRunCmd := commandRunCmd
+ defer func() { commandRunCmd = oldcommandRunCmd }()
+ commandRunCmd = func(cmd *exec.Cmd) (string, int, error) {
+ command = cmd.Args
+ return "Success", 0, nil
+ }
+ err := deployCSAPIFlows()
+ assert.NoError(t, err)
+ assert.Contains(t, command, "/home/aceuser/deps/CSAPI")
+ assert.Contains(t, command, "/home/aceuser/ace-server/run/CSAPI")
+
+ })
+ t.Run("Error copying files", func(t *testing.T) {
+ oldcommandRunCmd := commandRunCmd
+ defer func() { commandRunCmd = oldcommandRunCmd }()
+ commandRunCmd = func(cmd *exec.Cmd) (string, int, error) {
+ err := errors.New("Error running deploying BAR file")
+ return "Error running deploying BAR file", 1, err
+ }
+ err := deployCSAPIFlows()
+ assert.Error(t, err)
+ })
+ os.Unsetenv("CONNECTOR_SERVICE")
+ })
+
+}
+
+
+func Test_forceflowbasicauthServerConfUpdate(t *testing.T) {
+ t.Run("Golden path - Empty file gets populated with the right values", func(t *testing.T) {
+
+ oldReadServerConfFile := readServerConfFile
+ readServerConfFile = func() ([]byte, error) {
+ return []byte{}, nil
+ }
+ oldWriteServerConfFileLocal := writeServerConfFile
+ writeServerConfFile = func(content []byte) error {
+ return nil
+ }
+
+ err := forceflowbasicauthServerConfUpdate()
+ assert.NoError(t, err)
+ readServerConfFile = oldReadServerConfFile
+ writeServerConfFile = oldWriteServerConfFileLocal
+ })
+
+ t.Run("Existing value in server.conf.yaml", func(t *testing.T) {
+
+ serverconfMap := make(map[interface{}]interface{})
+ serverconfMap["forceServerHTTPSecurityProfile"] = "{DefaultPolicies}:SecProfLocal"
+ serverconfYaml, _ := yaml.Marshal(&serverconfMap)
+
+ oldReadServerConfFile := readServerConfFile
+ readServerConfFile = func() ([]byte, error) {
+ return serverconfYaml, nil
+ }
+ oldWriteServerConfFileLocal := writeServerConfFile
+ writeServerConfFile = func(content []byte) error {
+ return nil
+ }
+
+ err := forceflowbasicauthServerConfUpdate()
+ assert.NoError(t, err)
+ readServerConfFile = oldReadServerConfFile
+ writeServerConfFile = oldWriteServerConfFileLocal
+ })
+
+ t.Run("Error reading server.conf.yaml file", func(t *testing.T) {
+ oldReadServerConfFile := readServerConfFile
+ readServerConfFile = func() ([]byte, error) {
+ return nil, errors.New("Error reading server.conf.yaml")
+ }
+ oldWriteServerConfFileLocal := writeServerConfFile
+ writeServerConfFile = func(content []byte) error {
+ return nil
+ }
+
+ err := forceflowbasicauthServerConfUpdate()
+ assert.Error(t, err)
+ readServerConfFile = oldReadServerConfFile
+ writeServerConfFile = oldWriteServerConfFileLocal
+ })
+ t.Run("yaml.Marshal fails to execute properly", func(t *testing.T) {
+ oldYamlUnmarshal := yamlUnmarshal
+ yamlUnmarshal = func(in []byte, out interface{}) (err error) {
+ return errors.New("Error unmarshalling yaml")
+ }
+ oldYamlMarshal := yamlMarshal
+ yamlMarshal = func(in interface{}) (out []byte, err error) {
+ return nil, nil
+ }
+
+ err := forceflowbasicauthServerConfUpdate()
+ assert.Error(t, err)
+ assert.Equal(t, "Error unmarshalling yaml", err.Error())
+
+ yamlUnmarshal = oldYamlUnmarshal
+ yamlMarshal = oldYamlMarshal
+ })
+ t.Run("yaml.Marshal fails to execute properly", func(t *testing.T) {
+ oldYamlUnmarshal := yamlUnmarshal
+ yamlUnmarshal = func(in []byte, out interface{}) (err error) {
+ return nil
+ }
+ oldYamlMarshal := yamlMarshal
+ yamlMarshal = func(in interface{}) (out []byte, err error) {
+ return nil, errors.New("Error marshalling yaml")
+ }
+
+ err := forceflowbasicauthServerConfUpdate()
+ assert.Error(t, err)
+ assert.Equal(t, "Error marshalling yaml", err.Error())
+
+ yamlUnmarshal = oldYamlUnmarshal
+ yamlMarshal = oldYamlMarshal
+ })
+ t.Run("yaml.Marshal fails to execute properly", func(t *testing.T) {
+ oldYamlUnmarshal := yamlUnmarshal
+ yamlUnmarshal = func(in []byte, out interface{}) (err error) {
+ return nil
+ }
+ oldYamlMarshal := yamlMarshal
+ yamlMarshal = func(in interface{}) (out []byte, err error) {
+ return nil, nil
+ }
+ oldWriteServerConfFile := writeServerConfFile
+ writeServerConfFile = func(content []byte) error {
+ return errors.New("Error writing server.conf.yaml")
+ }
+ err := forceflowbasicauthServerConfUpdate()
+ assert.Error(t, err)
+ assert.Equal(t, "Error writing server.conf.yaml", err.Error())
+
+ yamlUnmarshal = oldYamlUnmarshal
+ yamlMarshal = oldYamlMarshal
+ writeServerConfFile = oldWriteServerConfFile
+ })
+}
diff --git a/cmd/runaceserver/main.go b/cmd/runaceserver/main.go
index 3a04ec6..add15c8 100644
--- a/cmd/runaceserver/main.go
+++ b/cmd/runaceserver/main.go
@@ -115,7 +115,7 @@ func doMain() error {
runOnly := os.Getenv("ACE_RUN_ONLY")
if runOnly == "true" || runOnly == "1" {
- log.Println("Run selected so skipping setup")
+ log.Println("Run selected so skipping setup")
} else {
log.Println("Checking for valid working directory")
err = createWorkDir()
@@ -125,6 +125,17 @@ func doMain() error {
return err
}
+ workdirShared := os.Getenv("WORKDIR-SHARED")
+ if workdirShared == "true" || workdirShared == "1" {
+ log.Println("Add symlink into shared workdir")
+ err = createWorkDirSymLink()
+ if err != nil {
+ logTermination(err)
+ performShutdown()
+ return err
+ }
+ }
+
// Note: this will do nothing if there are no crs set in the environment
err = configuration.SetupConfigurationsFiles(log, "/home/aceuser")
if err != nil {
@@ -163,6 +174,35 @@ func doMain() error {
performShutdown()
return err
}
+
+ // Deploy Connector Service API
+ err = deployCSAPIFlows()
+ if err != nil {
+ logTermination(err)
+ performShutdown()
+ return err
+ }
+
+ designerIntegrationFlows := os.Getenv("DESIGNER_INTEGRATION_FLOWS")
+ if designerIntegrationFlows == "true" {
+ err = deployIntegrationFlowResources()
+ if err != nil {
+ logTermination(err)
+ performShutdown()
+ return err
+ }
+ }
+
+ forceflowbasicauth := os.Getenv("FORCEFLOWBASICAUTH")
+ if forceflowbasicauth == "true" || forceflowbasicauth == "1" {
+ err = forceflowbasicauthServerConfUpdate()
+ if err != nil {
+ logTermination(err)
+ performShutdown()
+ return err
+ }
+ }
+
}
setupOnly := os.Getenv("ACE_SETUP_ONLY")
diff --git a/deps/CSAPI/META-INF/bar-refresh.links b/deps/CSAPI/META-INF/bar-refresh.links
new file mode 100644
index 0000000..44e994c
--- /dev/null
+++ b/deps/CSAPI/META-INF/bar-refresh.links
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/deps/CSAPI/META-INF/broker.xml b/deps/CSAPI/META-INF/broker.xml
new file mode 100644
index 0000000..1526b46
--- /dev/null
+++ b/deps/CSAPI/META-INF/broker.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/deps/CSAPI/META-INF/manifest.mf b/deps/CSAPI/META-INF/manifest.mf
new file mode 100644
index 0000000..55f313d
--- /dev/null
+++ b/deps/CSAPI/META-INF/manifest.mf
@@ -0,0 +1 @@
+srcSelected=false;showSrc=true;esql21VersionSelected=false;
\ No newline at end of file
diff --git a/deps/CSAPI/META-INF/service.log b/deps/CSAPI/META-INF/service.log
new file mode 100644
index 0000000..e6de405
--- /dev/null
+++ b/deps/CSAPI/META-INF/service.log
@@ -0,0 +1,36 @@
+
+==============================================
+
+!Wed Mar 23 13:16:28 GMT 2022
+Message flow CSAPI/Proxy.msgflow successfully loaded
+Message flow CSAPI/Proxy.msgflow successfully compiled
+Message flow CSAPI/Proxy.msgflow successfully added to archive file
+
+Node Flow Version Reason
+----------------------------------------------------------------------------------------------------
+Failure Handler Proxy 5.0 Generate 5.0 compatible ESQL by default.
+This compatibility level supports ESQL source code debugging.
+Deploying 5.0 compatible ESQL code will cause a syntax error on version 2.1 or previous brokers.
+Configure Request Proxy 5.0 Generate 5.0 compatible ESQL by default.
+This compatibility level supports ESQL source code debugging.
+Deploying 5.0 compatible ESQL code will cause a syntax error on version 2.1 or previous brokers.
+Message flow CSAPI/Proxy.msgflow successfully loaded
+Message flow CSAPI/Proxy.msgflow successfully compiled
+Message flow CSAPI/Proxy.msgflow successfully added to archive file
+
+Node Flow Version Reason
+----------------------------------------------------------------------------------------------------
+Failure Handler Proxy 5.0 Generate 5.0 compatible ESQL by default.
+This compatibility level supports ESQL source code debugging.
+Deploying 5.0 compatible ESQL code will cause a syntax error on version 2.1 or previous brokers.
+Configure Request Proxy 5.0 Generate 5.0 compatible ESQL by default.
+This compatibility level supports ESQL source code debugging.
+Deploying 5.0 compatible ESQL code will cause a syntax error on version 2.1 or previous brokers.
+
+Successfully added file CSAPI/application.descriptor to BAR file.
+
+Successfully added file CSAPI/application.descriptor to BAR file.
+
+Successfully added file CSAPI/application.descriptor to BAR file.
+
+Successfully added file CSAPI/application.descriptor to BAR file.
diff --git a/deps/CSAPI/META-INF/user.log b/deps/CSAPI/META-INF/user.log
new file mode 100644
index 0000000..1257a13
--- /dev/null
+++ b/deps/CSAPI/META-INF/user.log
@@ -0,0 +1,37 @@
+
+==============================================
+
+!Wed Mar 23 13:16:28 GMT 2022
+
+Processing file CSAPI/Proxy.msgflow
+Successfully added file CSAPI/Proxy.msgflow to archive file
+Elapsed time: 0.082 second(s).
+
+Processing file CSAPI/Proxy.msgflow
+Successfully added file CSAPI/Proxy.msgflow to archive file
+Elapsed time: 0.082 second(s).
+
+Processing file CSAPI/Proxy.msgflow
+Message flow "Proxy.msgflow" can be deployed as source since it does not include any subflows defined in the MSGFLOW files
+or any nodes unsupported by the source deploy. You may select -deployAsSource flag when building the
+BAR with MQSICREATEBAR command or do not select "Compile and in-line resources" build option on the BAR editor.
+
+==============================================
+
+!Wed Mar 23 13:16:28 GMT 2022
+
+Processing file CSAPI/application.descriptor.
+Successfully added file CSAPI/application.descriptor to BAR file.
+Elapsed time: 0 second(s).
+
+Successfully added file CSAPI/application.descriptor to BAR file.
+
+==============================================
+
+!Wed Mar 23 13:16:28 GMT 2022
+
+Processing file CSAPI/application.descriptor.
+Successfully added file CSAPI/application.descriptor to BAR file.
+Elapsed time: 0 second(s).
+
+Successfully added file CSAPI/application.descriptor to BAR file.
diff --git a/deps/CSAPI/Proxy.cmf b/deps/CSAPI/Proxy.cmf
new file mode 100644
index 0000000..3f91329
--- /dev/null
+++ b/deps/CSAPI/Proxy.cmf
@@ -0,0 +1,75 @@
+
+
+CREATE SCHEMA "" PATH ""
+
+CREATE COMPUTE MODULE Proxy_Configure_Request
+ CREATE FUNCTION Main() RETURNS BOOLEAN
+ BEGIN
+
+ SET OutputRoot = InputRoot;
+
+ /*
+LE section when "Set destination list" is checked on the input node:
+
+ (0x01000000:Name):HTTP = (
+ (0x01000000:Name):Input = (
+ (0x01000000:Name):RequestLine = (
+ (0x03000000:NameValue):Method = 'GET' (CHARACTER)
+ (0x03000000:NameValue):RequestURI = '/csapi/abc/def' (CHARACTER)
+ (0x03000000:NameValue):HTTPVersion = 'HTTP/1.1' (CHARACTER)
+ )
+ )
+ )
+*/
+ -- Keep everything after /csapi (include the slash)
+ IF LENGTH( InputRoot.HTTPInputHeader."X-Query-String" ) > 0 THEN
+ SET OutputLocalEnvironment.Destination.HTTP.RequestLine.RequestURI = SUBSTRING(InputLocalEnvironment.HTTP.Input.RequestLine.RequestURI FROM 7) || '?' || InputRoot.HTTPInputHeader."X-Query-String";
+ ELSE
+ SET OutputLocalEnvironment.Destination.HTTP.RequestLine.RequestURI = SUBSTRING(InputLocalEnvironment.HTTP.Input.RequestLine.RequestURI FROM 7);
+ END IF;
+ SET OutputLocalEnvironment.Destination.HTTP.RequestLine.Method = InputLocalEnvironment.HTTP.Input.RequestLine.Method;
+
+ RETURN TRUE;
+ END;
+
+END MODULE;
+CREATE SCHEMA "" PATH ""
+
+CREATE COMPUTE MODULE Proxy_Failure_Handler
+ CREATE FUNCTION Main() RETURNS BOOLEAN
+ BEGIN
+ SET OutputRoot = InputRoot;
+
+ -- Set response code
+ SET OutputLocalEnvironment.Destination.HTTP.ReplyStatusCode = 500;
+
+ if InputExceptionList IS NOT NULL THEN
+ -- Check the BIP message and put out an appropriate error message
+ DECLARE messageNumber INTEGER;
+ DECLARE messageText char;
+ CALL getLastExceptionDetail(InputExceptionList, messageNumber, messageText);
+
+ SET OutputRoot.JSON.Data.BIP.Number = messageNumber;
+ SET OutputRoot.JSON.Data.BIP.Message = messageText;
+ END IF;
+
+ -- Just forward on the original message
+
+
+ END;
+END MODULE;CREATE PROCEDURE getLastExceptionDetail(IN InputTree reference, OUT messageNumber integer, OUT messageText char)
+BEGIN
+ -- Create a reference to the first child of the exception list
+ declare ptrException reference to InputTree.*[1];
+ -- keep looping while the moves to the child of exception list work
+ WHILE lastmove(ptrException) DO
+ -- store the current values for the error number and text
+ IF ptrException.Number is not null THEN
+ SET messageNumber = ptrException.Number;
+ SET messageText = ptrException.Text;
+ END IF;
+ -- now move to the last child which should be the next exceptionlist
+ move ptrException lastchild;
+ END WHILE;
+END;
+
\ No newline at end of file
diff --git a/deps/CSAPI/application.descriptor b/deps/CSAPI/application.descriptor
new file mode 100644
index 0000000..166bf9e
--- /dev/null
+++ b/deps/CSAPI/application.descriptor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/go.mod b/go.mod
index 2ec7fa2..ec8fd03 100644
--- a/go.mod
+++ b/go.mod
@@ -9,7 +9,7 @@ require (
github.com/ghodss/yaml v1.0.0
github.com/gorilla/websocket v1.4.2
github.com/imdario/mergo v0.3.12
- github.com/prometheus/client_golang v1.11.0
+ github.com/prometheus/client_golang v1.11.1
github.com/prometheus/client_model v0.2.0
github.com/stretchr/testify v1.7.0
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
diff --git a/go.sum b/go.sum
index 05206e3..2d1ae38 100644
--- a/go.sum
+++ b/go.sum
@@ -280,6 +280,8 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
+github.com/prometheus/client_golang v1.11.1 h1:+4eQaD7vAZ6DsfsxB15hbE0odUjGI5ARs9yskGu1v4s=
+github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
diff --git a/internal/configuration/configuration.go b/internal/configuration/configuration.go
index e34d1f5..693dfb6 100644
--- a/internal/configuration/configuration.go
+++ b/internal/configuration/configuration.go
@@ -3,6 +3,7 @@ package configuration
import (
"archive/zip"
"bytes"
+ "context"
"crypto/tls"
"crypto/x509"
"encoding/base64"
@@ -18,7 +19,6 @@ import (
"strconv"
"strings"
"time"
- "context"
"github.com/Jeffail/gabs"
@@ -466,6 +466,7 @@ func runCommand(log logger.LoggerInterface, command string, params []string) err
err := cmd.Run()
if err != nil {
log.Printf("Error executing command: %s %s", stdout.String(), stderr.String())
+
} else {
log.Printf("Successfully executed command.")
}
diff --git a/internal/configuration/techConnectorsConfiguration.go b/internal/configuration/techConnectorsConfiguration.go
index 67e14b6..ae18732 100644
--- a/internal/configuration/techConnectorsConfiguration.go
+++ b/internal/configuration/techConnectorsConfiguration.go
@@ -148,7 +148,7 @@ func SetupTechConnectorsConfigurations(log logger.LoggerInterface, basedir strin
log.Printf("Connector %s accounts processed %v", connector, len(connectorAccounts))
}
} else {
- log.Printf("No accounts found for connector %s\n", connector)
+ log.Printf("No accounts found for connector %s", connector)
}
}
diff --git a/test-and-coverage.sh b/test-and-coverage.sh
new file mode 100755
index 0000000..d07730d
--- /dev/null
+++ b/test-and-coverage.sh
@@ -0,0 +1,38 @@
+#!/bin/bash -e
+
+# Array of packages at 100% test coverage - Once a package has been fully covered it will be added to this list
+COVERED_PACKAGES=('webadmin')
+TEST_OUTPUT=$(go test $(go list ./... | grep -v /test/) -covermode=atomic -coverprofile cover.out)
+COVERAGE_REGRESSION=false
+
+for i in ${COVERED_PACKAGES[@]}; do
+ COV=$(echo "$TEST_OUTPUT" | grep "$i" | awk '{ print $5 }')
+ if [[ "$COV" != "100.0%" ]]; then
+ echo "$i is not at 100% test coverage."
+ COVERAGE_REGRESSION=true
+ fi
+done
+
+if [[ $COVERAGE_REGRESSION == true ]]; then
+ echo "Please address the coverage regression."
+ exit 1
+fi
+
+
+# This is the current expected code coverage
+CURRENT_COVERAGE=58.1
+LATEST=$(go tool cover -func cover.out | grep total | awk '{print substr($3, 1, length($3)-1)}')
+echo "Latest coverage: $LATEST"
+echo "Expected Coverage: $CURRENT_COVERAGE"
+result=$(echo "$LATEST >= $CURRENT_COVERAGE" | bc -l)
+if [ $result -gt 0 ]; then
+ echo "PASSED - Coverage Check"
+else
+ echo "Failed to meet required coverage value: $CURRENT_COVERAGE"
+ exit 1
+
+fi
+if [ "$LATEST" != "$CURRENT_COVERAGE" ]; then
+ echo "\nFAILED - You must update the CURRENT_COVERAGE in travis to match the new benchmark: $LATEST"
+ exit 1
+fi
diff --git a/ubi/Dockerfile-legacy.aceonly b/ubi/Dockerfile-legacy.aceonly
index ba6d440..4648f0f 100644
--- a/ubi/Dockerfile-legacy.aceonly
+++ b/ubi/Dockerfile-legacy.aceonly
@@ -55,7 +55,7 @@ LABEL summary="$SUMMARY" \
# Add required license as text file in Liceses directory (GPL, MIT, APACHE, Partner End User Agreement, etc)
COPY /licenses/ /licenses/
-RUN microdnf update && microdnf install findutils util-linux unzip python3 tar procps openssl && microdnf clean all \
+RUN microdnf update && microdnf install findutils util-linux unzip python39 tar procps openssl && microdnf clean all \
&& ln -s /usr/bin/python3 /usr/local/bin/python \
&& mkdir /etc/ACEOpenTracing /opt/ACEOpenTracing /var/log/ACEOpenTracing && chmod 777 /var/log/ACEOpenTracing /etc/ACEOpenTracing
diff --git a/ubi/Dockerfile.aceonly b/ubi/Dockerfile.aceonly
index fdb85dd..aa57586 100644
--- a/ubi/Dockerfile.aceonly
+++ b/ubi/Dockerfile.aceonly
@@ -33,8 +33,8 @@ RUN tar -xzf $ACE_INSTALL --absolute-names --exclude ace-12.\*/tools --exclude a
# This is to delete any flash files which some customers consider a vulnerability - mostly used by googlelibs
RUN echo "Removing the following swf files" \
- && find . -name "*.swf" -type f \
- && find . -name "*.swf" -type f -delete
+ && find . -name "*.swf" -type f \
+ && find . -name "*.swf" -type f -delete
FROM registry.access.redhat.com/ubi8/ubi-minimal
@@ -61,9 +61,8 @@ LABEL summary="$SUMMARY" \
# Add required license as text file in Liceses directory (GPL, MIT, APACHE, Partner End User Agreement, etc)
COPY /licenses/ /licenses/
-RUN microdnf update && microdnf install findutils util-linux unzip python3 tar procps openssl && microdnf clean all \
- && ln -s /usr/bin/python3 /usr/local/bin/python \
- && mkdir /etc/ACEOpenTracing /opt/ACEOpenTracing /var/log/ACEOpenTracing && chmod 777 /var/log/ACEOpenTracing /etc/ACEOpenTracing
+RUN microdnf update && microdnf install findutils util-linux unzip tar procps openssl && microdnf clean all \
+ && mkdir /etc/ACEOpenTracing /opt/ACEOpenTracing /var/log/ACEOpenTracing && chmod 777 /var/log/ACEOpenTracing /etc/ACEOpenTracing
# Force reinstall tzdata package to get zoneinfo files
RUN microdnf reinstall tzdata -y
@@ -86,6 +85,7 @@ COPY *.sh /usr/local/bin/
COPY ubi/generic_invalid/invalid_license.msgflow /home/aceuser/temp/gen
COPY ubi/generic_invalid/InvalidLicenseJava.jar /home/aceuser/temp/gen
COPY ubi/generic_invalid/application.descriptor /home/aceuser/temp
+COPY deps/CSAPI /home/aceuser/deps/CSAPI
# Create a user to run as, create the ace workdir, and chmod script files
RUN /opt/ibm/ace-12/ace make registry global accept license silently \
@@ -116,4 +116,4 @@ USER 1000
# Set entrypoint to run management script
-ENTRYPOINT ["runaceserver"]
+ENTRYPOINT ["runaceserver"]
\ No newline at end of file
diff --git a/ubi/create-default-mq-kdb.sh b/ubi/create-default-mq-kdb.sh
old mode 100644
new mode 100755
index dadbee3..68ac10c
--- a/ubi/create-default-mq-kdb.sh
+++ b/ubi/create-default-mq-kdb.sh
@@ -42,4 +42,3 @@ else
$MQSI_JREPATH/bin/keytool -importkeystore -srckeystore $MQSI_JREPATH/lib/security/cacerts -srcstorepass changeit -destkeystore /tmp/java-cacerts.p12 -deststoretype pkcs12 -deststorepass changeit
/opt/mqm/bin/runmqakm -keydb -convert -db /tmp/java-cacerts.p12 -old_format p12 -new_format kdb -pw changeit -target /tmp/mqcacerts.kdb -stash
fi
-
diff --git a/ubi/install-mq-client-prereqs.sh b/ubi/install-mq-client-prereqs.sh
old mode 100644
new mode 100755
diff --git a/ubi/install-mq.sh b/ubi/install-mq.sh
old mode 100644
new mode 100755
index be096bd..cc8b077
--- a/ubi/install-mq.sh
+++ b/ubi/install-mq.sh
@@ -109,3 +109,4 @@ rm -rf ${DIR_TMP}
# Create the directory for MQ configuration files
install --directory --mode 2775 --owner 1001 --group root /etc/mqm
+