Skip to content

Commit

Permalink
Merge pull request #13 from SoftwareAG/feature-migration-1019
Browse files Browse the repository at this point in the history
Feature migration 1019
  • Loading branch information
ck-c8y authored Feb 27, 2024
2 parents 3bea646 + 601cf04 commit b527743
Show file tree
Hide file tree
Showing 55 changed files with 17,618 additions and 30,651 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ settings.json
setEnv.sh
**/dist
.env
attic/
attic
.angular
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,10 @@ The modal dialog provides the option:

On the monitoring tab you can view the latest alarms and events for the Streaming Analytics Engine. This is especially helpful if after an upload of a new extension no extension is loaded.

This is an indication that the engine was started in **Safe Mode**, i.e. without loading any extension. In this case you have to delete the latest uploaded extension and restart the engine again.
The property `is_safe_mode` is an indication if the engine was started in [Safe Mode](https://cumulocity.com/guides/streaming-analytics/troubleshooting/#safe-mode-on-startup), i.e. without loading any extension. In this case you have to delete the latest uploaded extension and restart the engine again.

![Monitoring](resources/images/monitoring.png)


## Installation of plugin as community plugin

> **NOTE**
Expand Down
45 changes: 26 additions & 19 deletions analytics-service/c8y_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@


class C8YAgent:
APAMA_CTRL_APPLICATION_NAME = "apama-ctrl-1c-4g"

def __init__(self):
self._logger = logging.getLogger("C8YAgent")
self._logger.setLevel(logging.DEBUG)
Expand All @@ -48,50 +46,59 @@ def restart_cep(self, request_headers):
resource="/service/cep/restart", json={}
)
except Exception as e:
self._logger.error(f"Ignoring exception!", exc_info=True)
self._logger.error(f"Exception:", exc_info=True)
# for keys,values in request_headers.items():
# self._logger.info(f"Headers: {keys} {values}")

self._logger.info(f"Restarted CEP!")

def get_cep_id(self, request_headers):
def get_cep_operationobject_id(self, request_headers):
try:
self._logger.info(f"Retrieving CEP id ...")
apps = self.c8yapp.get_tenant_instance(
headers=request_headers
).applications.select(name=self.APAMA_CTRL_APPLICATION_NAME)
self._logger.info(f"Retrieving id of operation object for CEP ...")

response = self.c8yapp.get_tenant_instance(headers=request_headers).get(
resource=f"/service/cep/diagnostics/apamaCtrlStatus")
try:
app_id = None
cep_id = None
for app in apps:
app_id = app.id
self._logger.info(f"Found app id: {app_id}")
# break
query = f"$filter=applicationId eq '{app_id}' and name eq '{self.APAMA_CTRL_APPLICATION_NAME}'"
app_id = response["microservice_application_id"]
microservice_name = response["microservice_name"]
cep_operationobject_id = None
query = f"applicationId eq '{app_id}' and name eq '{microservice_name}'"

self._logger.info(f"Build filter: {query}")

managed_objects_app = self.c8yapp.get_tenant_instance(
headers=request_headers
).inventory.select(query)
).inventory.select(query=query)
managed_object_id = None
for managed_object in managed_objects_app:
self._logger.info(
f"Found managed object: {managed_object.id} for cep app: {app_id}"
)
managed_object_id = managed_object
cep_id = managed_object_id.id
cep_operationobject_id = managed_object_id.id
break
if managed_object_id == None:
self._logger.error(f"Not found !")
return None
return {"id": cep_id}
return {"id": cep_operationobject_id}
except:
self._logger.error(
f"Error finding app id: {app_id}",
exc_info=True,
)
except Exception as e:
self._logger.error(f"Ignoring exception!", exc_info=True)
self._logger.error(f"Exception:", exc_info=True)
# for keys,values in request_headers.items():
# self._logger.info(f"Headers: {keys} {values}")

def get_cep_ctrl_status(self, request_headers):
try:
self._logger.info(f"Retrieving CEP control status ...")

response = self.c8yapp.get_tenant_instance(headers=request_headers).get(
resource=f"/service/cep/diagnostics/apamaCtrlStatus")
return response
except Exception as e:
self._logger.error(f"Exception:", exc_info=True)
# for keys,values in request_headers.items():
# self._logger.info(f"Headers: {keys} {values}")
23 changes: 14 additions & 9 deletions analytics-service/flask_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,27 +211,32 @@ def get_cep_extension_metadata():
# return the managedObject that represents the cep ctrl microservice
# returns:
# id
# @app.route("/cep/diagnostic", methods=["GET"])
# def get_cep_id():
# cep_id = {}
# return cep_id, 200
@app.route("/cep/id", methods=["GET"])
def get_cep_operationobject_id():
result = agent.get_cep_operationobject_id(request_headers=request.headers)
if (result == None):
return f"Not found", 400
return jsonify(result)


@app.route("/cep/id", methods=["GET"])
def get_cep_id():
result = agent.get_cep_id(request_headers=request.headers)
# return status of cep ctrl microservice
# returns:
# status
# @app.route("/cep/status", methods=["GET"])
@app.route("/cep/status", methods=["GET"])
def get_get_cep_ctrl_status():
result = agent.get_cep_ctrl_status(request_headers=request.headers)
if (result == None):
return f"Not found", 400
return jsonify(result)



# this endpoint was only exposed for test purposes
# @app.route("/cep/restart", methods=["PUT"])
# def restart():
# agent.restart_cep(request_headers=request.headers)
# return f"OK", 200


def extract_path(path):
# Extract information from the API URL
delimiters = r"[/?]"
Expand Down
138 changes: 138 additions & 0 deletions analytics-ui/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
module.exports = {
root: true,
env: {
browser: true,
es2021: true
},
overrides: [
{
files: ['*.ts'],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module'
},
plugins: ['import', '@typescript-eslint', '@angular-eslint'],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@angular-eslint/recommended',
// This is required if you use inline templates in Components
'plugin:@angular-eslint/template/process-inline-templates'
],
rules: {
semi: ['error'],
'spaced-comment': [
'error',
'always',
{
line: {
exceptions: ['/']
},
markers: ['//////////']
}
],
'func-names': ['error', 'never'],
'no-use-before-define': 'off',
'comma-dangle': [
'error',
{
arrays: 'ignore',
objects: 'ignore',
imports: 'ignore',
exports: 'ignore',
functions: 'never'
}
],
strict: ['error', 'function'],
'no-param-reassign': [
'error',
{
props: false
}
],
'no-plusplus': 'off',
'no-redeclare': 'off',
'no-extra-semi': 'error',
'no-multi-spaces': 'error',
'no-trailing-spaces': 'error',
'no-multiple-empty-lines': 'error',
'no-underscore-dangle': 0,
'prefer-template': 'warn',
'linebreak-style': 'off',
'object-property-newline': 'off',
'prefer-destructuring': [
'error',
{
VariableDeclarator: {
array: true,
object: true
},
AssignmentExpression: {
array: false,
object: false
}
},
{
enforceForRenamedProperties: false
}
],
'max-len': 'off',
'arrow-parens': 'off',
'function-paren-newline': 'off',
indent: 'off',
'implicit-arrow-linebreak': 'off',
'object-curly-newline': [
'error',
{
consistent: true
}
],
'operator-linebreak': 'off',
'space-before-function-paren': 'off',
'no-confusing-arrow': 'off',
quotes: [
'error',
'single',
{
avoidEscape: true,
allowTemplateLiterals: false
}
],
'@typescript-eslint/no-inferrable-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/ban-types': [
'error',
{
types: {
Function: false
}
}
],
'no-prototype-builtins': 'warn',
'@angular-eslint/directive-selector': [
'error',
{ type: 'attribute', prefix: ['c8y', 'a17t'], style: 'camelCase' }
],
'@angular-eslint/component-selector': [
'error',
{ type: 'element', prefix: ['c8y', 'a17t'], style: 'kebab-case' }
],
'import/no-unused-modules': 'error',
'@angular-eslint/component-class-suffix': 'off',
}
},
{
files: ['*.component.html'],
plugins: ['@angular-eslint/template'],
extends: ['plugin:@angular-eslint/template/recommended'],
parser: '@angular-eslint/template-parser',
parserOptions: {
project: './tsconfig.json',
ecmaVersion: 'latest',
sourceType: 'module'
},
rules: {}
}
]
};
6 changes: 6 additions & 0 deletions analytics-ui/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"singleQuote": true,
"semi": true,
"trailingComma" : "none",
"bracketSpacing": true
}
60 changes: 30 additions & 30 deletions analytics-ui/cumulocity.config.ts
Original file line number Diff line number Diff line change
@@ -1,58 +1,58 @@
import { EnvironmentOptions } from "@c8y/devkit/dist/options";
import { author, description, version, license } from "./package.json";
import { EnvironmentOptions } from '@c8y/devkit/dist/options';
import { author, description, version, license } from './package.json';

export default {
runTime: {
author,
description,
license,
version,
name: "Analytics Extension", // key for repository connect
contextPath: "sag-ps-pkg-analytics-extension", // key for repository connect
key: "sag-ps-pkg-analytics-extension-pluginn-key", // key for repository connect
name: 'Analytics Extension', // key for repository connect
contextPath: 'sag-ps-pkg-analytics-extension', // key for repository connect
key: 'sag-ps-pkg-analytics-extension-pluginn-key', // key for repository connect
contentSecurityPolicy:
"base-uri 'none'; default-src 'self' 'unsafe-inline' http: https: ws: wss:; connect-src 'self' http: https: ws: wss:; script-src 'self' *.bugherd.com *.twitter.com *.twimg.com *.aptrinsic.com 'unsafe-inline' 'unsafe-eval' data:; style-src * 'unsafe-inline' blob:; img-src * data: blob:; font-src * data:; frame-src *; worker-src 'self' blob:;",
dynamicOptionsUrl: "/apps/public/public-options/options.json",
dynamicOptionsUrl: '/apps/public/public-options/options.json',
remotes: {
"sag-ps-pkg-analytics-extension": ["AnalyticsExtensionModule"],
'sag-ps-pkg-analytics-extension': ['AnalyticsExtensionModule'],
},
package: "plugin",
package: 'plugin',
isPackage: true,
noAppSwitcher: true,
exports: [
{
name: "Analytics Builder Extension",
module: "AnalyticsExtensionModule",
path: "./src/analytics-extension.module",
description: "Adds Extensions for the Analytics Builder",
name: 'Analytics Builder Extension',
module: 'AnalyticsExtensionModule',
path: './src/analytics-extension.module',
description: 'Adds Extensions for the Analytics Builder',
},
],
},
buildTime: {
federation: [
"@angular/animations",
"@angular/cdk",
"@angular/common",
"@angular/compiler",
"@angular/core",
"@angular/forms",
"@angular/platform-browser",
"@angular/platform-browser-dynamic",
"@angular/router",
"@angular/upgrade",
"@c8y/client",
"@c8y/ngx-components",
"ngx-bootstrap",
"@ngx-translate/core",
'@angular/animations',
'@angular/cdk',
'@angular/common',
'@angular/compiler',
'@angular/core',
'@angular/forms',
'@angular/platform-browser',
'@angular/platform-browser-dynamic',
'@angular/router',
'@angular/upgrade',
'@c8y/client',
'@c8y/ngx-components',
'ngx-bootstrap',
'@ngx-translate/core',
],
copy: [
{
from: "../resources/images",
to: "resources/images",
from: '../resources/images',
to: 'resources/images',
},
{
from: "../README.md",
to: "README.md",
from: '../README.md',
to: 'README.md',
},
],
},
Expand Down
Loading

0 comments on commit b527743

Please sign in to comment.