├── .gitignore
├── .project
├── Attribution.txt
├── Dockerfile
├── Dockerfile.build
├── Jenkinsfile
├── LICENSE
├── Makefile
├── README.md
├── ReleaseNotes.md
├── docker-files
├── application.properties
├── bootstrap.properties
└── rule-template.drl
├── pom.xml
├── raml
└── support-rulesengine.raml
└── src
├── main
├── java
│ └── org
│ │ └── edgexfoundry
│ │ ├── Application.java
│ │ ├── HeartBeat.java
│ │ ├── controller
│ │ ├── PingController.java
│ │ ├── RuleEngineController.java
│ │ └── impl
│ │ │ ├── LocalErrorController.java
│ │ │ ├── PingControllerImpl.java
│ │ │ └── RuleEngineControllerImpl.java
│ │ ├── engine
│ │ ├── CommandExecutor.java
│ │ ├── RuleCreator.java
│ │ └── RuleEngine.java
│ │ ├── export
│ │ └── registration
│ │ │ ├── ExportClient.java
│ │ │ └── ExportClientImpl.java
│ │ ├── messaging
│ │ └── ZeroMQEventSubscriber.java
│ │ └── rule
│ │ └── domain
│ │ ├── Action.java
│ │ ├── Condition.java
│ │ ├── Rule.java
│ │ └── ValueCheck.java
└── resources
│ ├── application.properties
│ ├── banner.txt
│ ├── bootstrap.properties
│ └── rule-template.drl
└── test
├── java
└── org
│ └── edgexfoundry
│ ├── controller
│ ├── PingControllerTest.java
│ ├── RuleEngineControllerTest.java
│ └── integration
│ │ └── RuleEngineControllerTest.java
│ ├── engine
│ ├── CommandExecutorTest.java
│ ├── RuleCreatorTest.java
│ ├── RunEngineTest.java
│ └── integration
│ │ └── RuleEngineTest.java
│ ├── export
│ └── registration
│ │ └── integration
│ │ └── web
│ │ ├── ExportClientImplTest.java
│ │ ├── LocalErrorControllerTest.java
│ │ ├── TestHttpServletRequest.java
│ │ └── TestHttpServletResponse.java
│ ├── messaging
│ └── ZeroMQEventSubscriberTest.java
│ └── rule
│ └── domain
│ └── data
│ ├── ActionData.java
│ ├── ConditionData.java
│ ├── RuleData.java
│ └── ValueCheckData.java
└── resources
├── bad-rule-template.drl
├── raml
└── support-rulesengine.raml
├── rule-template.drl
└── rule.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | ### /.gitignore-boilerplates/Global/Eclipse.gitignore
2 | *.pydevproject
3 | .metadata
4 | bin/
5 | tmp/**
6 | tmp/**/*
7 | *.tmp
8 | *.bak
9 | *.swp
10 | *~.nib
11 | local.properties
12 | .loadpath
13 | .classpath
14 | .factorypath
15 | .settings/
16 | .springBeans
17 |
18 | # External tool builders
19 | .externalToolBuilders/
20 |
21 | # Locally stored "Eclipse launch configurations"
22 | *.launch
23 |
24 | # CDT-specific
25 | .cproject
26 |
27 | # PDT-specific
28 | .buildpath
29 |
30 | ### .gitignore-boilerplates/Global/OSX.gitignore
31 | .DS_Store
32 | .AppleDouble
33 | .LSOverride
34 | Icon
35 |
36 | # Thumbnails
37 | ._*
38 |
39 | # Files that might appear on external disk
40 | .Spotlight-V100
41 | .Trashes
42 |
43 | ### .gitignore-boilerplates/Java.gitignore
44 | *.class
45 |
46 | # Package Files #
47 | *.jar
48 | *.war
49 | *.ear
50 |
51 | # Intellij
52 | .idea/
53 | *.iml
54 | *.iws
55 |
56 | # Maven
57 | log/
58 | target/
59 | /.apt_generated/
60 | .mvn/
61 | .m2/
62 | mvnw
63 | mvnw.cmd
64 |
65 | #EdgeX logging
66 | logs/
67 | /bin/
68 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | support-rulesengine
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.sonarlint.eclipse.core.sonarlintBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.m2e.core.maven2Builder
20 |
21 |
22 |
23 |
24 |
25 | org.eclipse.jdt.core.javanature
26 | org.eclipse.m2e.core.maven2Nature
27 |
28 |
29 |
--------------------------------------------------------------------------------
/Attribution.txt:
--------------------------------------------------------------------------------
1 | The following open source projects are referenced by Support Rules Engine:
2 |
3 | Spring Cloud (Apache 2.0) - http://projects.spring.io/spring-cloud/
4 | https://github.com/spring-cloud/spring-cloud-release/blob/master/LICENSE.txt
5 |
6 | Spring Boot (Apache 2.0) - https://projects.spring.io/spring-boot/
7 | https://github.com/spring-projects/spring-boot/blob/master/LICENSE.txt
8 |
9 | Spring Framework (Apache 2.0) - http://projects.spring.io/spring-framework/
10 | https://github.com/spring-projects/spring-framework
11 |
12 | Log4J (Apache 2.0) - https://logging.apache.org/log4j/2.x/
13 | https://logging.apache.org/log4j/2.0/license.html
14 |
15 | Resteasy, JBoss (Apache 2.0) - http://resteasy.jboss.org/
16 | https://github.com/resteasy/Resteasy/blob/master/License.html
17 |
18 | Freemarker (Apache 2.0) - http://freemarker.org/
19 | http://freemarker.org/docs/app_license.html
20 |
21 | GSON (Apache 2.0) - https://github.com/google/gson
22 | https://github.com/google/gson/blob/master/LICENSE
23 |
24 | Jackson Core (Apache 2.0) - https://github.com/FasterXML/jackson-core/wiki
25 | https://github.com/FasterXML/jackson-core/wiki
26 |
27 | JeroMQ (Mozilla Public License 2.0) - https://github.com/zeromq/jeromq
28 | https://github.com/zeromq/jeromq/blob/master/LICENSE
29 |
30 |
31 | Junit (EPL 1.0) - http://junit.org/junit4/
32 | http://junit.org/junit4/license.html
33 |
34 |
35 | Kie Drools (Apache 2.0) - http://www.kiegroup.org/
36 | https://github.com/kiegroup/drools/blob/master/LICENSE-ASL-2.0.txt
37 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright 2016-2017 Dell Inc.
3 | # Copyright 2018 Dell Technologies, Inc.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 | ###############################################################################
18 | # Docker image for Rules Engine micro service
19 | # FROM java:8
20 | FROM alpine:3.6
21 |
22 | RUN apk --update add openjdk8-jre
23 |
24 | # environment variables
25 | ENV APP_DIR=/edgex/edgex-support-rulesengine
26 | ENV TEMPLATE_DIR=/edgex/edgex-support-rulesengine/templates
27 | ENV APP=support-rulesengine.jar
28 | ENV APP_PORT=48075
29 |
30 | #copy JAR and property files to the image
31 | COPY target/*.jar $APP_DIR/$APP
32 | COPY docker-files/*.properties $APP_DIR/
33 | #copy drool template to templates location
34 | COPY docker-files/*.drl $TEMPLATE_DIR/
35 |
36 | RUN mkdir /edgex/edgex-support-rulesengine/rules
37 | RUN echo "this directory is reserved for EdgeX Foundry Drools rule files" > /edgex/edgex-support-rulesengine/rules/README
38 |
39 | #expose support rulesengine port
40 | EXPOSE $APP_PORT
41 |
42 | #set the working directory
43 | WORKDIR $APP_DIR
44 |
45 | #kick off the micro service
46 | ENTRYPOINT java -jar -Djava.security.egd=file:/dev/urandom -Xmx100M $APP
--------------------------------------------------------------------------------
/Dockerfile.build:
--------------------------------------------------------------------------------
1 | FROM maven:3.6.2
2 |
3 | RUN apt-get update && \
4 | apt-get install -y make
5 |
6 | COPY --from=docker:latest /usr/local/bin/docker /usr/local/bin/docker
--------------------------------------------------------------------------------
/Jenkinsfile:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2019 Intel Corporation
3 | //
4 | // Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | // You may obtain a copy of the License at
7 | //
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | //
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 | //
16 |
17 | loadGlobalLibrary()
18 |
19 | pipeline {
20 | agent {
21 | label 'centos7-docker-4c-2g'
22 | }
23 |
24 | options {
25 | timestamps()
26 | }
27 |
28 | stages {
29 | stage('LF Prep') {
30 | steps {
31 | edgeXSetupEnvironment()
32 | edgeXSemver 'init'
33 | script {
34 | def semverVersion = edgeXSemver()
35 | env.setProperty('VERSION', semverVersion)
36 | sh 'echo $VERSION > VERSION'
37 | stash name: 'semver', includes: '.semver/**,VERSION', useDefaultExcludes: false
38 | }
39 | }
40 | }
41 |
42 | stage('Multi-Arch Build') {
43 | // fan out
44 | parallel {
45 | stage('Build amd64') {
46 | agent {
47 | label 'centos7-docker-4c-2g'
48 | }
49 | stages {
50 | stage('Phase 1') {
51 | agent {
52 | dockerfile {
53 | filename 'Dockerfile.build'
54 | label 'centos7-docker-4c-2g'
55 | args '-v /var/run/docker.sock:/var/run/docker.sock -v $PWD:/root -w /root -u 0:0 --privileged'
56 | reuseNode true
57 | }
58 | }
59 | stages {
60 | stage('Test') {
61 | steps {
62 | sh 'make test'
63 | }
64 | }
65 | stage('Maven Package') {
66 | when { expression { edgex.isReleaseStream() } }
67 |
68 | steps {
69 | sh 'make build'
70 | }
71 | }
72 | stage('Docker Build') {
73 | when { expression { edgex.isReleaseStream() } }
74 |
75 | steps {
76 | unstash 'semver'
77 |
78 | sh 'echo Currently Building version: `cat ./VERSION`'
79 |
80 | script {
81 | // This is the main docker image that will be pushed
82 | // BASE image = image from above
83 | image_amd64 = docker.build(
84 | 'docker-support-rulesengine',
85 | "--label 'git_sha=${env.GIT_COMMIT}' ."
86 | )
87 | }
88 | }
89 | }
90 | }
91 | }
92 |
93 | // this should be back on the original node that has the tools required to run the login script
94 | stage('Phase 2') {
95 | stages {
96 | stage('Docker Push') {
97 | when { expression { edgex.isReleaseStream() } }
98 |
99 | steps {
100 | script {
101 | edgeXDockerLogin(settingsFile: 'support-rulesengine-settings')
102 |
103 | docker.withRegistry("https://${env.DOCKER_REGISTRY}:10004") {
104 | image_amd64.push("${env.SEMVER_BRANCH}")
105 | image_amd64.push("${env.VERSION}")
106 | image_amd64.push("${env.GIT_COMMIT}-${env.VERSION}")
107 | }
108 | }
109 | }
110 | }
111 | }
112 | }
113 | }
114 | }
115 | stage('Build arm64') {
116 | agent {
117 | label 'ubuntu18.04-docker-arm64-4c-16g'
118 | }
119 | stages {
120 | stage('Phase 1') {
121 | agent {
122 | dockerfile {
123 | filename 'Dockerfile.build'
124 | label 'ubuntu18.04-docker-arm64-4c-16g'
125 | args '-v /var/run/docker.sock:/var/run/docker.sock -v $PWD:/root -w /root -u 0:0 --privileged'
126 | reuseNode true
127 | }
128 | }
129 | stages {
130 | stage('Test') {
131 | steps {
132 | sh 'make test'
133 | }
134 | }
135 | stage('Maven Package') {
136 | when { expression { edgex.isReleaseStream() } }
137 |
138 | steps {
139 | sh 'make build'
140 | }
141 | }
142 | stage('Docker Build') {
143 | when { expression { edgex.isReleaseStream() } }
144 |
145 | steps {
146 | unstash 'semver'
147 |
148 | sh 'echo Currently Building version: `cat ./VERSION`'
149 |
150 | script {
151 | // This is the main docker image that will be pushed
152 | // BASE image = image from above
153 | image_arm64 = docker.build(
154 | 'docker-support-rulesengine-arm64',
155 | "--label 'git_sha=${env.GIT_COMMIT}' ."
156 | )
157 | }
158 | }
159 | }
160 | }
161 | }
162 |
163 | stage('Phase 2') {
164 | stages {
165 | stage('Docker Push') {
166 | when { expression { edgex.isReleaseStream() } }
167 |
168 | steps {
169 | script {
170 | edgeXDockerLogin(settingsFile: 'support-rulesengine-settings')
171 |
172 | docker.withRegistry("https://${env.DOCKER_REGISTRY}:10004") {
173 | image_arm64.push("${env.SEMVER_BRANCH}")
174 | image_arm64.push("${env.VERSION}")
175 | image_arm64.push("${env.GIT_COMMIT}-${env.VERSION}")
176 | }
177 | }
178 | }
179 | }
180 | }
181 | }
182 | }
183 | }
184 | }
185 | }
186 |
187 | stage('SemVer Tag') {
188 | when { expression { edgex.isReleaseStream() } }
189 | steps {
190 | unstash 'semver'
191 | sh 'echo v${VERSION}'
192 | edgeXSemver('tag')
193 | edgeXInfraLFToolsSign(command: 'git-tag', version: 'v${VERSION}')
194 | }
195 | }
196 |
197 | stage('Semver Bump Pre-Release Version') {
198 | when { expression { edgex.isReleaseStream() } }
199 | steps {
200 | edgeXSemver('bump pre')
201 | edgeXSemver('push')
202 | }
203 | }
204 | }
205 |
206 | post {
207 | failure {
208 | script {
209 | currentBuild.result = "FAILED"
210 | }
211 | }
212 | always {
213 | edgeXInfraPublish()
214 | }
215 | }
216 | }
217 |
218 | def loadGlobalLibrary(branch = '*/master') {
219 | library(identifier: 'edgex-global-pipelines@master',
220 | retriever: legacySCM([
221 | $class: 'GitSCM',
222 | userRemoteConfigs: [[url: 'https://github.com/edgexfoundry/edgex-global-pipelines.git']],
223 | branches: [[name: branch]],
224 | doGenerateSubmoduleConfigurations: false,
225 | extensions: [[
226 | $class: 'SubmoduleOption',
227 | recursiveSubmodules: true,
228 | ]]]
229 | )
230 | ) _
231 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright 2017 Dell, Inc.
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: clean build
2 |
3 | # VERSION file is not needed for local development, In the CI/CD pipeline, a temporary VERSION file is written
4 | # if you need a specific version, just override below
5 | VERSION=$(shell cat ./VERSION 2>/dev/null || echo 0.0.0)
6 |
7 | # This pulls the version of the SDK from the go.mod file. If the SDK is the only required module,
8 | # it must first remove the word 'required' so the offset of $2 is the same if there are multiple required modules
9 |
10 | MICROSERVICE=support-rulesengine
11 | MAVEN_OPTIONS="-Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true -Dmaven.wagon.http.ssl.ignore.validity.dates=true"
12 | GIT_SHA=$(shell git rev-parse HEAD)
13 |
14 | build:
15 | mvn package $(MAVEN_OPTIONS)
16 |
17 | # NOTE: This is only used for local development. Jenkins CI does not use this make target
18 | docker:
19 | docker build \
20 | --build-arg http_proxy \
21 | --build-arg https_proxy \
22 | -f Dockerfile \
23 | --label "git_sha=$(GIT_SHA)" \
24 | -t edgexfoundry/docker-support-rulesengine:$(GIT_SHA) \
25 | -t edgexfoundry/docker-support-rulesengine:$(VERSION) \
26 | -t edgexfoundry/docker-support-rulesengine:latest \
27 | .
28 |
29 | test:
30 | mvn test $(MAVEN_OPTIONS)
31 |
32 | clean:
33 | mvn clean $(MAVEN_OPTIONS)
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Main Author: Jim White
2 |
3 | Copyright 2016-19, Dell, Inc.
4 |
5 | Rules Engine Micro Service receives data from the export service (via 0MQ) and then triggers actuation based on event data it receives and analyzes. Built on Drools technology.
6 |
7 |
--------------------------------------------------------------------------------
/ReleaseNotes.md:
--------------------------------------------------------------------------------
1 | # v1.0 (5/28/2019)
2 | #Release Notes
3 | Updated to ignore CBOR data messages.
4 |
5 | # v0.2 (10/20/2017)
6 | # Release Notes
7 |
8 | ## Notable Changes
9 | The Barcelona Release (v 0.2) of the Support Rules Engine micro service includes the following:
10 | * Application of Google Style Guidelines to the code base
11 | * Increase in unit/intergration tests from 27 tests to 115 tests
12 | * POM changes for appropriate repository information for distribution/repos management, checkstyle plugins, etc.
13 | * Removed all references to unfinished DeviceManager work as part of Dell Fuse
14 | * Added Dockerfile for creation of micro service targeted for ARM64
15 | * Added interfaces for all Controller classes
16 |
17 | ## Bug Fixes
18 | * Removed OS specific file path for logging file
19 | * Provide option to include stack trace in log outputs
20 |
21 | ## Pull Request/Commit Details
22 | - [#11](https://github.com/edgexfoundry/support-rulesengine/pull/11) - Remove staging plugin contributed by Jeremy Phelps ([JPWKU](https://github.com/JPWKU))
23 | - [#10](https://github.com/edgexfoundry/support-rulesengine/pull/10) - Fixes Maven artifact dependency path contributed by Tyler Cox ([trcox](https://github.com/trcox))
24 | - [#9](https://github.com/edgexfoundry/support-rulesengine/pull/9) - harden work in progress. Added google style checks, added repos to p… contributed by Jim White ([jpwhitemn](https://github.com/jpwhitemn))
25 | - [#8](https://github.com/edgexfoundry/support-rulesengine/pull/8) - Removed device manager url refs in properties files contributed by Jim White ([jpwhitemn](https://github.com/jpwhitemn))
26 | - [#7](https://github.com/edgexfoundry/support-rulesengine/pull/7) - Added support for aarch64 arch contributed by ([feclare](https://github.com/feclare))
27 | - [#6](https://github.com/edgexfoundry/support-rulesengine/pull/6) - Adds Docker build capability contributed by Tyler Cox ([trcox](https://github.com/trcox))
28 | - [#5](https://github.com/edgexfoundry/support-rulesengine/issues/5) - is rulesengine working currently?
29 | - [#4](https://github.com/edgexfoundry/support-rulesengine/pull/4) - Fixes Log File Path contributed by Tyler Cox ([trcox](https://github.com/trcox))
30 | - [#3](https://github.com/edgexfoundry/support-rulesengine/issues/3) - Log File Path not Platform agnostic
31 | - [#2](https://github.com/edgexfoundry/support-rulesengine/pull/2) - Add distributionManagement for artifact storage contributed by Andrew Grimberg ([tykeal](https://github.com/tykeal))
32 | - [#1](https://github.com/edgexfoundry/support-rulesengine/pull/1) - Contributed Project Fuse source code contributed by Tyler Cox ([trcox](https://github.com/trcox))
33 |
34 |
--------------------------------------------------------------------------------
/docker-files/application.properties:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright 2016-17 Dell Inc.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | # @microservice: support-rulesengine
17 | # @author: Jim White, Dell
18 | # @version: 1.0.0
19 | ###############################################################################
20 | #--Docker container specific app properties -----
21 | #-----------------General Config-----------------------------------------------
22 | #every 5 minutes (in milliseconds)
23 | heart.beat.time=300000
24 | #messages
25 | heart.beat.msg=Support Rules Engine data heart beat
26 | app.open.msg=This is the Support Rules Engine Microservice.
27 | # set port (override Spring boot default port 8080 )
28 | server.port=48075
29 | #-----------------App Service Configurable Rules Config----------------------------------------
30 | #Turn on/off registration of rules engine as app-service-configurable client.
31 | #Set to false to receive messages directly from core data
32 | export.client=false
33 | expect.serializedjava=false
34 | #export.client.registration.url=http://localhost:48071/api/v1
35 | export.client.registration.url=http://edgex-export-client:48071/api/v1
36 | export.client.registration.name=EdgeXRulesEngine
37 | #use port 5566 when connected to app-service-configurable
38 | #use port 5563 when connected to core data directly
39 | export.zeromq.port=5566
40 | #export.zeromq.port=5563
41 | #export.zeromq.host=tcp://localhost
42 | export.zeromq.host=tcp://edgex-app-service-configurable-rules
43 | #how long to wait to retry registration
44 | export.client.registration.retry.time=10000
45 | #how many times to try registration before exiting
46 | export.client.registration.retry.attempts=100
47 | #-----------------Logging Config-----------------------------------------------
48 | #logging levels (used to control log4j entries)
49 | logging.level.org.springframework=ERROR
50 | logging.level.org.apache=ERROR
51 | logging.level.org.edgexfoundry=INFO
52 | #log files are rotated after 10MB by default in Spring boot
53 | logging.file=/edgex/logs/edgex-support-rulesengine.log
54 | #print stack traces with errors on REST calls
55 | print.stacktrace=false
56 | #-----------------Drools Config-----------------------------------------------
57 | #Drools drl resource path
58 | #rules.default.path=/edgex/rules
59 | rules.default.path=/edgex/edgex-support-rulesengine/rules
60 | rules.packagename=org.edgexfoundry.rules
61 | rules.fileextension=.drl
62 | #rules.template.path=./src/main/resources
63 | #rules.template.path=/edgex/templates
64 | rules.template.path=/edgex/edgex-support-rulesengine/templates
65 | rules.template.name=rule-template.drl
66 | rules.template.encoding=UTF-8
67 | #IOT core data database service connection information
68 | #core.db.command.url=http://localhost:48082/api/v1/device
69 | core.db.command.url=http://edgex-core-command:48082/api/v1/device
70 | #IOT metadata database service connection information
71 | #meta.db.addressable.url=http://localhost:48081/api/v1/addressable
72 | #meta.db.deviceservice.url=http://localhost:48081/api/v1/deviceservice
73 | #meta.db.deviceprofile.url=http://localhost:48081/api/v1/deviceprofile
74 | #meta.db.device.url=http://localhost:48081/api/v1/device
75 | #meta.db.devicereport.url=http://localhost:48081/api/v1/devicereport
76 | #meta.db.command.url=http://localhost:48081/api/v1/command
77 | #meta.db.event.url=http://localhost:48081/api/v1/event
78 | #meta.db.schedule.url=http://localhost:48081/api/v1/schedule
79 | #meta.db.provisionwatcher.url=http://localhost:48081/api/v1/provisionwatcher
80 | meta.db.addressable.url=http://edgex-core-metadata:48081/api/v1/addressable
81 | meta.db.deviceservice.url=http://edgex-core-metadata:48081/api/v1/deviceservice
82 | meta.db.deviceprofile.url=http://edgex-core-metadata:48081/api/v1/deviceprofile
83 | meta.db.device.url=http://edgex-core-metadata:48081/api/v1/device
84 | meta.db.devicereport.url=http://edgex-core-metadata:48081/api/v1/devicereport
85 | meta.db.command.url=http://edgex-core-metadata:48081/api/v1/command
86 | meta.db.event.url=http://edgex-core-metadata:48081/api/v1/event
87 | meta.db.schedule.url=http://edgex-core-metadata:48081/api/v1/schedule
88 | meta.db.provisionwatcher.url=http://edgex-core-metadata:48081/api/v1/provisionwatcher
89 | #-----------------Remote Logging Config------------------------------------------
90 | logging.remote.enable=false
91 | #logging.remote.url=http://localhost:48061/api/v1/logs
92 | logging.remote.url=http://edgex-support-logging:48061/api/v1/logs
93 |
--------------------------------------------------------------------------------
/docker-files/bootstrap.properties:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright 2016-2017 Dell Inc.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | ###############################################################################
17 | spring.application.name=edgex-support-rulesengine
18 | spring.cloud.consul.host=edgex-core-consul
19 | spring.cloud.consul.port=8500
20 | spring.cloud.consul.config.profileSeparator=;
21 | spring.cloud.consul.enabled=false
22 | spring.profiles.active=docker
--------------------------------------------------------------------------------
/docker-files/rule-template.drl:
--------------------------------------------------------------------------------
1 | package org.edgexfoundry.rules;
2 | global org.edgexfoundry.engine.CommandExecutor executor;
3 | global org.edgexfoundry.support.logging.client.EdgeXLogger logger;
4 | import org.edgexfoundry.domain.core.Event;
5 | import org.edgexfoundry.domain.core.Reading;
6 | import java.util.Map;
7 | rule "${rulename}"
8 | when
9 | $e:Event($rlist: readings && device=="${conddeviceid}")
10 | <#if valuechecks??>
11 | <#assign idx = 0>
12 | <#list valuechecks as valuecheck>
13 | $r${idx}:Reading(name=="${valuecheck.parameter}" && ${valuecheck.operand1} ${valuecheck.operation} ${valuecheck.operand2}) from $rlist
14 | <#assign idx = idx + 1>
15 | #list>
16 | #if>
17 | then
18 | executor.fireCommand("${actiondeviceid}", "${actioncommandid}", "${commandbody}");
19 | logger.info("${log}");
20 | end
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
9 |
12 | 4.0.0
13 | org.edgexfoundry
14 | support-rulesengine
15 | 1.1.0
16 | EdgeX Foundry Rules Engine Micro Service
17 | EdgeX Foundry Rules Engine Micro Service
18 |
19 |
20 | Brixton.SR5
21 | 6.4.0.Final
22 | 3.0.13.Final
23 | 0.5.1
24 | 0.5.0
25 | 0.2.0
26 | 0.5.0
27 | 0.5.0
28 | 0.5.0
29 | 0.5.0
30 | 2.5.5
31 | UTF-8
32 | UTF-8
33 | 1.8
34 | https://nexus.edgexfoundry.org
35 | content/repositories
36 | 2.17
37 |
38 |
39 |
40 | org.springframework.boot
41 | spring-boot-starter-parent
42 | 1.3.7.RELEASE
43 |
44 |
45 |
46 |
47 | snapshots
48 | EdgeX Snapshot Repository
49 | ${nexusproxy}/${repobasepath}/snapshots
50 |
51 |
52 |
53 |
54 |
55 | org.springframework.boot
56 | spring-boot-starter-web
57 |
58 |
59 | org.springframework.boot
60 | spring-boot-starter
61 |
62 |
63 | org.springframework.boot
64 | spring-boot-starter-logging
65 |
66 |
67 |
68 |
69 | org.springframework.boot
70 | spring-boot-starter-log4j
71 |
72 |
73 | log4j
74 | log4j
75 |
76 |
77 | org.jboss.resteasy
78 | resteasy-client
79 | ${resteasy.version}
80 |
81 |
82 | org.slf4j
83 | slf4j-simple
84 |
85 |
86 |
87 |
88 | org.jboss.resteasy
89 | resteasy-jackson-provider
90 | ${resteasy.version}
91 |
92 |
93 | org.freemarker
94 | freemarker
95 |
96 |
97 | com.fasterxml.jackson.core
98 | jackson-annotations
99 |
100 |
101 | org.zeromq
102 | jeromq
103 | ${zeromq.version}
104 |
105 |
106 | org.springframework.cloud
107 | spring-cloud-starter-consul-all
108 |
109 |
110 | javax.ws.rs
111 | jsr311-api
112 |
113 |
114 | com.google.code.findbugs
115 | jsr305
116 |
117 |
118 |
119 |
120 | org.edgexfoundry
121 | core-domain
122 | ${core-domain.version}
123 |
124 |
125 | org.edgexfoundry
126 | export-domain
127 | ${export-domain.version}
128 |
129 |
130 | org.edgexfoundry
131 | core-command-client
132 | ${core-command-client.version}
133 |
134 |
135 | org.edgexfoundry
136 | core-exception
137 | ${core-exception.version}
138 |
139 |
140 | org.kie
141 | kie-ci
142 | ${drools.version}
143 |
144 |
145 | org.edgexfoundry
146 | core-test
147 | ${core-test.version}
148 | test
149 |
150 |
151 | org.edgexfoundry
152 | support-logging-client
153 | ${support-logging-client.version}
154 |
155 |
156 | junit
157 | junit
158 | test
159 |
160 |
161 | org.springframework.boot
162 | spring-boot-starter-test
163 | test
164 |
165 |
166 | org.springframework
167 | spring-test
168 | test
169 |
170 |
171 |
172 |
173 |
174 |
175 | org.springframework.cloud
176 | spring-cloud-dependencies
177 | ${spring.cloud.version}
178 | pom
179 | import
180 |
181 |
182 |
183 |
184 |
185 |
186 | RequiresNone
187 |
188 | org.edgexfoundry.test.category.RequiresNone
189 |
190 |
191 | true
192 |
193 |
194 |
195 | Requires
196 |
197 | org.edgexfoundry.test.category.RequiresSpring
198 | org.edgexfoundry.test.category.RequiresWeb
199 | org.edgexfoundry.test.category.RequiresMongo
200 |
201 |
202 |
203 |
204 | ${project.artifactId}
205 |
206 |
207 | org.springframework.boot
208 | spring-boot-maven-plugin
209 |
210 |
211 | org.apache.maven.plugins
212 | maven-compiler-plugin
213 |
214 | ${java.version}
215 | ${java.version}
216 |
217 |
218 |
219 | maven-surefire-plugin
220 |
221 | ${testcase.groups}
222 |
223 |
224 |
225 | org.apache.maven.plugins
226 | maven-dependency-plugin
227 | 3.0.1
228 |
229 |
230 |
231 | org.edgexfoundry
232 | support-rulesengine
233 | ${version}
234 | .
235 | support-rulesengine.jar
236 |
237 |
238 |
239 |
240 |
241 | org.apache.maven.plugins
242 | maven-checkstyle-plugin
243 | ${checkstyle.plugin.version}
244 |
245 |
246 | validate
247 | validate
248 |
249 | google_checks.xml
250 | true
251 | error
252 | false
253 | false
254 | true
255 | ${project.build.directory}/edgex-checkstyles-result.xml
256 |
257 |
258 | check
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
268 |
269 | org.eclipse.m2e
270 | lifecycle-mapping
271 | 1.0.0
272 |
273 |
274 |
275 |
276 |
277 | org.apache.maven.plugins
278 | maven-checkstyle-plugin
279 | [2.17,)
280 |
281 | check
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 | releases
298 | EdgeX Release Repository
299 | ${nexusproxy}/${repobasepath}/releases
300 |
301 |
302 | staging
303 | EdgeX Staging Repository
304 | ${nexusproxy}/${repobasepath}/staging
305 |
306 |
307 | snapshots
308 | EdgeX Snapshot Repository
309 | ${nexusproxy}/${repobasepath}/snapshots
310 |
311 |
312 |
313 |
--------------------------------------------------------------------------------
/raml/support-rulesengine.raml:
--------------------------------------------------------------------------------
1 | #%RAML 0.8
2 | title: support-rulesengine
3 | version: "1.0.0"
4 | baseUri: "http://localhost:48075/api/v1"
5 | schemas:
6 | -
7 | rule: '{"type":"object","$schema":"http://json-schema.org/draft-03/schema#","description":"EdgeX Support Rules Engine rule","title":"rule","properties":{"name":{"type":"string","required":true,"title":"name"}, "action":{"type":"object","properties":{"device":{"type":"string","required":true,"title":"device"},"command":{"type":"string","required":true,"title":"command"},"body":{"type":"string","required":true,"title":"body"}}}, "condition":{"type":"object","properties":{"device":{"type":"string","required":true,"title":"device"},"checks":{"type":"array","required":false,"title":"checks","items":{"type":"object","properties":{"parameter":{"type":"string","required":false,"title":"parameter"},"operand1":{"type":"string","required":false,"title":"operand1"},"operation":{"type":"string","required":false,"title":"operation"},"operand2":{"type":"string","required":false,"title":"operand2"}}},"uniqueItems":false}}}, "log":{"type":"string","required":false,"title":"log"}}}'
8 | /rule:
9 | displayName: rules
10 | description: example - http://localhost:48075/api/v1/rule
11 | post:
12 | description: Add a new rule. ServcieException (HTTP 503) for unknown or unanticipated issues.
13 | displayName: add a rule
14 | body:
15 | application/json:
16 | schema: rule
17 | example: '{"name":"motortoofastsignal", "condition": {"device":"562114e9e4b0385849b96cd8","checks":[ {"parameter":"RPM", "operand1":"Integer.parseInt(value)", "operation":">","operand2":"1200" } ] }, "action" : {"device":"56325f7ee4b05eaae5a89ce1","command":"56325f6de4b05eaae5a89cdc","body":"{\\\"value\\\":\\\"3\\\"}"},"log":"Patlite warning triggered for engine speed too high" }'
18 | responses:
19 | "200":
20 | description: boolean indicating success of adding the new rule
21 | "503":
22 | description: for unknown or unanticipated issues
23 | get:
24 | description: Return all rule names. ServcieException (HTTP 503) for unknown or unanticipated issues.
25 | displayName: get all rule names
26 | responses:
27 | "200":
28 | description: list of strings
29 | body:
30 | application/json:
31 | example: '["motortoofastsignal"]'
32 | "503":
33 | description: for unknown or unanticipated issues.
34 | /rule/name/{rulename}:
35 | displayName: rule (by name)
36 | description: example - http://localhost:48075/api/v1/rule/name/temptoohi (where temptoohi is the name of a rule)
37 | uriParameters:
38 | rulename:
39 | displayName: rulename
40 | description: Unique name of the rule
41 | type: string
42 | required: true
43 | repeat: false
44 | delete:
45 | description: Remove the rule designated by name. ServcieException (HTTP 503) for unknown or unanticipated issues.
46 | displayName: remove a rule by name
47 | responses:
48 | "200":
49 | description: boolean indicating success of the remove operation
50 | "503":
51 | description: for unknown or unanticipated issues.
52 | /ping:
53 | displayName: Ping Resource
54 | description: example - http://localhost:48075/api/v1/ping
55 | get:
56 | description: Test service providing an indication that the service is available.
57 | displayName: service up check
58 | responses:
59 | "200":
60 | description: return value of "pong"
61 | "503":
62 | description: for unknown or unanticipated issues
63 |
--------------------------------------------------------------------------------
/src/main/java/org/edgexfoundry/Application.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry;
20 |
21 | import org.edgexfoundry.messaging.ZeroMQEventSubscriber;
22 | import org.springframework.boot.SpringApplication;
23 | import org.springframework.boot.autoconfigure.SpringBootApplication;
24 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
25 | import org.springframework.context.ConfigurableApplicationContext;
26 | import org.springframework.scheduling.annotation.EnableAsync;
27 |
28 | @SpringBootApplication(scanBasePackages = {"org.edgexfoundry", "org.springframework.cloud.client"})
29 | @EnableAsync
30 | @EnableDiscoveryClient
31 | public class Application {
32 |
33 | public static void main(String[] args) {
34 | ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);
35 | String welcomeMsg = ctx.getEnvironment().getProperty("app.open.msg");
36 | ZeroMQEventSubscriber sub = ctx.getBean(ZeroMQEventSubscriber.class);
37 | System.out.println(welcomeMsg);
38 | sub.receive();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/org/edgexfoundry/HeartBeat.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry;
20 |
21 | import org.springframework.beans.factory.annotation.Value;
22 | import org.springframework.scheduling.annotation.EnableScheduling;
23 | import org.springframework.scheduling.annotation.Scheduled;
24 | import org.springframework.stereotype.Component;
25 |
26 | @EnableScheduling
27 | @Component
28 | public class HeartBeat {
29 |
30 | private static final org.edgexfoundry.support.logging.client.EdgeXLogger logger =
31 | org.edgexfoundry.support.logging.client.EdgeXLoggerFactory.getEdgeXLogger(HeartBeat.class);
32 |
33 | @Value("${heart.beat.msg}")
34 | private String heartBeatMsg;
35 |
36 | @Scheduled(fixedRateString = "${heart.beat.time}")
37 | public void pulse() {
38 | logger.info(heartBeatMsg);
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/org/edgexfoundry/controller/PingController.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.controller;
20 |
21 | public interface PingController {
22 |
23 | /**
24 | * Test service providing an indication that the service is available.
25 | *
26 | * @throws ServcieException (HTTP 503) for unknown or unanticipated issues
27 | */
28 | String ping();
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/org/edgexfoundry/controller/RuleEngineController.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.controller;
20 |
21 | import java.util.List;
22 |
23 | import org.edgexfoundry.rule.domain.Rule;
24 | import org.springframework.web.bind.annotation.PathVariable;
25 | import org.springframework.web.bind.annotation.RequestBody;
26 |
27 | public interface RuleEngineController {
28 |
29 | List ruleNames();
30 |
31 | boolean addRule(@RequestBody Rule rule);
32 |
33 | boolean removeRule(@PathVariable String rulename);
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/org/edgexfoundry/controller/impl/LocalErrorController.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.controller.impl;
20 |
21 | import java.util.Map;
22 |
23 | import javax.servlet.http.HttpServletRequest;
24 | import javax.servlet.http.HttpServletResponse;
25 |
26 | import org.springframework.beans.factory.annotation.Autowired;
27 | import org.springframework.beans.factory.annotation.Value;
28 | import org.springframework.boot.autoconfigure.web.ErrorAttributes;
29 | import org.springframework.boot.autoconfigure.web.ErrorController;
30 | import org.springframework.web.bind.annotation.RequestMapping;
31 | import org.springframework.web.bind.annotation.RestController;
32 | import org.springframework.web.context.request.RequestAttributes;
33 | import org.springframework.web.context.request.ServletRequestAttributes;
34 |
35 | @RestController
36 | public class LocalErrorController implements ErrorController {
37 | private static final String PATH = "/error";
38 |
39 | @Value("${print.stacktrace:false}")
40 | private boolean printTraces;
41 |
42 | @Autowired
43 | private ErrorAttributes errorAttributes;
44 |
45 | @RequestMapping(value = PATH)
46 | public String error(HttpServletRequest request, HttpServletResponse response) {
47 | Map errorInfo = getErrorAttributes(request, printTraces);
48 | return errorInfo.get("message") + "\n\n" + errorInfo.get("trace");
49 | }
50 |
51 | @Override
52 | public String getErrorPath() {
53 | return PATH;
54 | }
55 |
56 | private Map getErrorAttributes(HttpServletRequest request,
57 | boolean includeStackTrace) {
58 | RequestAttributes requestAttributes = new ServletRequestAttributes(request);
59 | return errorAttributes.getErrorAttributes(requestAttributes, includeStackTrace);
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/org/edgexfoundry/controller/impl/PingControllerImpl.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.controller.impl;
20 |
21 | import org.edgexfoundry.controller.PingController;
22 | import org.edgexfoundry.exception.controller.ServiceException;
23 | import org.springframework.web.bind.annotation.RequestMapping;
24 | import org.springframework.web.bind.annotation.RequestMethod;
25 | import org.springframework.web.bind.annotation.RestController;
26 |
27 | @RestController
28 | @RequestMapping("/api/v1/ping")
29 | public class PingControllerImpl implements PingController {
30 |
31 | private static final org.edgexfoundry.support.logging.client.EdgeXLogger logger =
32 | org.edgexfoundry.support.logging.client.EdgeXLoggerFactory
33 | .getEdgeXLogger(PingControllerImpl.class);
34 |
35 | /**
36 | * Test service providing an indication that the service is available.
37 | *
38 | * @throws ServcieException (HTTP 503) for unknown or unanticipated issues
39 | */
40 | @Override
41 | @RequestMapping(method = RequestMethod.GET)
42 | public String ping() {
43 | try {
44 | return "pong";
45 | } catch (Exception e) {
46 | logger.error("Error on ping: " + e.getMessage());
47 | throw new ServiceException(e);
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/org/edgexfoundry/controller/impl/RuleEngineControllerImpl.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.controller.impl;
20 |
21 | import java.util.List;
22 |
23 | import org.edgexfoundry.controller.RuleEngineController;
24 | import org.edgexfoundry.engine.RuleCreator;
25 | import org.edgexfoundry.engine.RuleEngine;
26 | import org.edgexfoundry.exception.controller.ServiceException;
27 | import org.edgexfoundry.rule.domain.Rule;
28 | import org.springframework.beans.factory.annotation.Autowired;
29 | import org.springframework.web.bind.annotation.PathVariable;
30 | import org.springframework.web.bind.annotation.RequestBody;
31 | import org.springframework.web.bind.annotation.RequestMapping;
32 | import org.springframework.web.bind.annotation.RequestMethod;
33 | import org.springframework.web.bind.annotation.RestController;
34 |
35 | @RestController
36 | @RequestMapping("/api/v1/rule")
37 | public class RuleEngineControllerImpl implements RuleEngineController {
38 |
39 | private static final org.edgexfoundry.support.logging.client.EdgeXLogger logger =
40 | org.edgexfoundry.support.logging.client.EdgeXLoggerFactory
41 | .getEdgeXLogger(RuleEngineControllerImpl.class);
42 |
43 | @Autowired
44 | private RuleEngine engine;
45 |
46 | @Autowired
47 | private RuleCreator creator;
48 |
49 | @RequestMapping(method = RequestMethod.GET)
50 | @Override
51 | public List ruleNames() {
52 | try {
53 | return engine.getRulenames();
54 | } catch (Exception e) {
55 | logger.error("Problem getting rule names");
56 | throw new ServiceException(e);
57 | }
58 | }
59 |
60 | @RequestMapping(method = RequestMethod.POST)
61 | @Override
62 | public boolean addRule(@RequestBody Rule rule) {
63 | try {
64 | engine.addRule(creator.createDroolRule(rule), rule.getName());
65 | logger.info("Rule named: " + rule.getName() + " added.");
66 | return true;
67 | } catch (Exception e) {
68 | logger.error("Problem adding a new rule called: " + rule.getName());
69 | throw new ServiceException(e);
70 | }
71 | }
72 |
73 | @RequestMapping(value = "/name/{rulename}", method = RequestMethod.DELETE)
74 | @Override
75 | public boolean removeRule(@PathVariable String rulename) {
76 | try {
77 | engine.removeRule(rulename);
78 | logger.info("Rule named: " + rulename + " removed");
79 | return true;
80 | } catch (Exception e) {
81 | logger.error("Problem removing the rule called: " + rulename);
82 | throw new ServiceException(e);
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/main/java/org/edgexfoundry/engine/CommandExecutor.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.engine;
20 |
21 | import org.edgexfoundry.controller.CmdClient;
22 | import org.springframework.beans.factory.annotation.Autowired;
23 | import org.springframework.scheduling.annotation.Async;
24 | import org.springframework.stereotype.Component;
25 |
26 | @Component
27 | public class CommandExecutor {
28 |
29 | @Autowired
30 | private CmdClient client;
31 |
32 | private static final org.edgexfoundry.support.logging.client.EdgeXLogger logger =
33 | org.edgexfoundry.support.logging.client.EdgeXLoggerFactory
34 | .getEdgeXLogger(CommandExecutor.class);
35 |
36 | @Async
37 | public void fireCommand(String deviceId, String commandId, String body) {
38 | logger.info(
39 | "Sending request to: " + deviceId + "for command: " + commandId + " with body: " + body);
40 | try {
41 | // for now - all rule engine requests are puts
42 | forwardRequest(deviceId, commandId, body, true);
43 | } catch (Exception exception) {
44 | logger.error("Problem sending command to the device service " + exception);
45 | }
46 | }
47 |
48 | private void forwardRequest(String id, String commandId, String body, boolean isPut) {
49 | if (client != null) {
50 | if (isPut)
51 | logger.debug("Resposne from command put is: " + client.put(id, commandId, body));
52 | else
53 | logger.debug("Resposne from command get is: " + client.get(id, commandId));
54 | } else {
55 | logger.error("Command Client not available - no command sent for: " + id + " to " + commandId
56 | + " containing: " + body);
57 | }
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/org/edgexfoundry/engine/RuleCreator.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.engine;
20 |
21 | import java.io.File;
22 | import java.io.IOException;
23 | import java.io.StringWriter;
24 | import java.io.Writer;
25 | import java.util.HashMap;
26 | import java.util.Map;
27 |
28 | import javax.annotation.PostConstruct;
29 |
30 | import org.edgexfoundry.rule.domain.Rule;
31 | import org.springframework.beans.factory.annotation.Value;
32 | import org.springframework.stereotype.Component;
33 |
34 | import freemarker.template.Configuration;
35 | import freemarker.template.Template;
36 | import freemarker.template.TemplateException;
37 | import freemarker.template.TemplateExceptionHandler;
38 |
39 | @Component
40 | public class RuleCreator {
41 |
42 | private static final org.edgexfoundry.support.logging.client.EdgeXLogger logger =
43 | org.edgexfoundry.support.logging.client.EdgeXLoggerFactory.getEdgeXLogger(RuleCreator.class);
44 |
45 | @Value("${rules.template.path}")
46 | private String templateLocation;
47 |
48 | @Value("${rules.template.name}")
49 | private String templateName;
50 |
51 | @Value("${rules.template.encoding}")
52 | private String templateEncoding;
53 |
54 | private Configuration cfg;
55 |
56 | @PostConstruct
57 | public void init() throws IOException {
58 | try {
59 | cfg = new Configuration(Configuration.getVersion());
60 | cfg.setDirectoryForTemplateLoading(new File(templateLocation));
61 | cfg.setDefaultEncoding(templateEncoding);
62 | cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
63 | } catch (IOException e) {
64 | logger.error("Problem getting rule template location." + e.getMessage());
65 | throw e;
66 | }
67 | }
68 |
69 | private Map createMap(Rule rule) {
70 | Map map = new HashMap<>();
71 | map.put("rulename", rule.getName());
72 | map.put("conddeviceid", rule.getCondition().getDevice());
73 | map.put("valuechecks", rule.getCondition().getChecks());
74 | map.put("actiondeviceid", rule.getAction().getDevice());
75 | map.put("actioncommandid", rule.getAction().getCommand());
76 | map.put("commandbody", rule.getAction().getBody());
77 | map.put("log", rule.getLog());
78 | return map;
79 | }
80 |
81 | public String createDroolRule(Rule rule) throws TemplateException, IOException {
82 | try {
83 | Template temp = cfg.getTemplate(templateName);
84 | Writer out = new StringWriter();
85 | temp.process(createMap(rule), out);
86 | return out.toString();
87 | } catch (IOException iE) {
88 | logger.error("Problem getting rule template file." + iE.getMessage());
89 | throw iE;
90 | } catch (TemplateException tE) {
91 | logger.error("Problem writing Drool rule." + tE.getMessage());
92 | throw tE;
93 | } catch (Exception e) {
94 | logger.error("Problem creating rule: " + e.getMessage());
95 | throw e;
96 | }
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/src/main/java/org/edgexfoundry/engine/RuleEngine.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.engine;
20 |
21 | import java.io.BufferedWriter;
22 | import java.io.File;
23 | import java.io.FileWriter;
24 | import java.io.IOException;
25 | import java.util.ArrayList;
26 | import java.util.Collection;
27 | import java.util.List;
28 |
29 | import javax.annotation.PostConstruct;
30 |
31 | import org.edgexfoundry.domain.core.Event;
32 | import org.edgexfoundry.exception.controller.ServiceException;
33 | import org.kie.api.KieBase;
34 | import org.kie.api.KieBaseConfiguration;
35 | import org.kie.api.KieServices;
36 | import org.kie.api.builder.KieBuilder;
37 | import org.kie.api.builder.KieFileSystem;
38 | import org.kie.api.builder.Message.Level;
39 | import org.kie.api.definition.KiePackage;
40 | import org.kie.api.definition.rule.Rule;
41 | import org.kie.api.runtime.KieContainer;
42 | import org.kie.api.runtime.KieSession;
43 | import org.kie.internal.conf.ConstraintJittingThresholdOption;
44 | import org.kie.internal.io.ResourceFactory;
45 | import org.springframework.beans.factory.annotation.Autowired;
46 | import org.springframework.beans.factory.annotation.Value;
47 | import org.springframework.stereotype.Component;
48 |
49 | @Component
50 | public class RuleEngine {
51 |
52 | private static final org.edgexfoundry.support.logging.client.EdgeXLogger logger =
53 | org.edgexfoundry.support.logging.client.EdgeXLoggerFactory.getEdgeXLogger(RuleEngine.class);
54 |
55 | @Value("${rules.default.path}")
56 | private String resourceFilePath;
57 |
58 | @Value("${rules.packagename}")
59 | private String packageName;
60 |
61 | @Value("${rules.fileextension}")
62 | private String ruleFileExtension;
63 |
64 | @Autowired
65 | private CommandExecutor executor;
66 |
67 | private KieBase kbase;
68 | private KieFileSystem kfs;
69 |
70 | @PostConstruct
71 | public void init() {
72 | logger.debug("initializing Drools Kies");
73 | initKie();
74 | }
75 |
76 | public void execute(Object object) {
77 | try {
78 | KieSession ksession = kbase.newKieSession();
79 | if (!getRulenames().isEmpty()) {
80 | if (executor != null) {
81 | ksession.setGlobal("executor", executor);
82 | ksession.setGlobal("logger", logger);
83 | ksession.insert(object);
84 | int rulesFired = ksession.fireAllRules();
85 | logger.debug("Number of rules fired on event: " + rulesFired);
86 | if (rulesFired > 0) {
87 | logger.info("Event triggered " + rulesFired + "rules: " + (Event) object);
88 | }
89 | } else
90 | logger.error("Command Executor not available - no command sent for event: " + object);
91 | } else {
92 | logger.debug("No rules in the system - skipping firing rules");
93 | }
94 | ksession.dispose();
95 | } catch (Exception e) {
96 | logger.error("Error during rules enging processing: " + e.getMessage());
97 | }
98 | }
99 |
100 | public void addRule(String newRule, String rulename) throws IOException {
101 | String filename = getFileName(rulename);
102 | writeRule(newRule, filename);
103 | loadRule(filename);
104 | logger.info("new rule: " + rulename + " added.");
105 | initKie();
106 | }
107 |
108 | public boolean removeRule(String rulename) throws IOException {
109 | String filename = getFileName(rulename);
110 | if (kbase.getRule(packageName, rulename) != null)
111 | kbase.removeRule(packageName, rulename);
112 | kfs.delete(filename);
113 | // goofey - but the file won't delete but will allow to be overwritten
114 | // with nothing this allows the rule to go away
115 | boolean success = writeRule("", filename);
116 | logger.info("rule: " + rulename + " removed.");
117 | return success;
118 | }
119 |
120 | public List getRulenames() {
121 | List result = new ArrayList<>();
122 | try {
123 | KiePackage kpkg = kbase.getKiePackage(packageName);
124 | if (kpkg != null) {
125 | Collection rules = kpkg.getRules();
126 | if (rules != null) {
127 | for (Rule rule : rules) {
128 | result.add(rule.getName());
129 | }
130 | }
131 | }
132 | return result;
133 | } catch (Exception ex) {
134 | logger.error(ex.getMessage());
135 | throw new ServiceException(ex);
136 | }
137 | }
138 |
139 | public String getResourceFilePath() {
140 | return resourceFilePath;
141 | }
142 |
143 | public String getPackageName() {
144 | return packageName;
145 | }
146 |
147 | public String getRuleFileExtension() {
148 | return ruleFileExtension;
149 | }
150 |
151 | private String getFileName(String rulename) {
152 | createDirectory();
153 | return resourceFilePath + "/" + rulename + ruleFileExtension;
154 | }
155 |
156 | private void createDirectory() {
157 | File ruleDirectory = new File(resourceFilePath);
158 | if (!ruleDirectory.exists())
159 | ruleDirectory.mkdir();
160 | }
161 |
162 | private boolean writeRule(String rule, String filename) throws IOException {
163 | try (FileWriter fileWriter = new FileWriter(new File(filename));
164 | BufferedWriter writer = new BufferedWriter(fileWriter)) {
165 | writer.write(rule);
166 | writer.flush();
167 | writer.close();
168 | return true;
169 | } catch (IOException e) {
170 | logger.error("Problem writing file: " + filename);
171 | throw e;
172 | }
173 | }
174 |
175 | private void loadRule(String fileName) {
176 | kfs.write(ResourceFactory.newFileResource(fileName));
177 | }
178 |
179 | private void uploadDroolFiles() {
180 | logger.info("Starting Drools with drl files from: " + resourceFilePath);
181 | File directory = new File(resourceFilePath);
182 | File[] fList = directory.listFiles();
183 | logger.info("Uploading Drool rules...");
184 | if (fList != null && fList.length > 0) {
185 | for (File file : fList) {
186 | kfs.write(ResourceFactory.newFileResource(resourceFilePath + "/" + file.getName()));
187 | logger.info("... " + file.getName());
188 | }
189 | } else {
190 | logger.info("...no rules found to upload");
191 | }
192 | }
193 |
194 | private void initKie() {
195 | KieServices ks = KieServices.Factory.get();
196 | kfs = ks.newKieFileSystem();
197 | uploadDroolFiles();
198 | KieBuilder kbuilder = ks.newKieBuilder(kfs);
199 | kbuilder.buildAll();
200 | if (kbuilder.getResults().hasMessages(Level.ERROR)) {
201 | throw new IllegalArgumentException(kbuilder.getResults().toString());
202 | }
203 | KieContainer kcontainer = ks.newKieContainer(kbuilder.getKieModule().getReleaseId());
204 | KieBaseConfiguration kbConfig = KieServices.Factory.get().newKieBaseConfiguration();
205 | kbConfig.setOption(ConstraintJittingThresholdOption.get(-1));
206 | kbase = kcontainer.newKieBase(kbConfig);
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/src/main/java/org/edgexfoundry/export/registration/ExportClient.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.export.registration;
20 |
21 | import javax.ws.rs.Consumes;
22 | import javax.ws.rs.DELETE;
23 | import javax.ws.rs.GET;
24 | import javax.ws.rs.POST;
25 | import javax.ws.rs.Path;
26 | import javax.ws.rs.PathParam;
27 |
28 | import org.edgexfoundry.domain.export.ExportRegistration;
29 |
30 | public interface ExportClient {
31 |
32 | @GET
33 | @Path("/registration/name/{name}")
34 | ExportRegistration exportRegistrationByName(@PathParam("name") String name);
35 |
36 | @POST
37 | @Path("/registration")
38 | @Consumes("application/json")
39 | String register(ExportRegistration registration);
40 |
41 | @DELETE
42 | @Path("/registration/name/{name}")
43 | boolean deleteByName(@PathParam("name") String name);
44 |
45 | @DELETE
46 | @Path("/registration/id/{id}")
47 | boolean delete(@PathParam("id") String id);
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/org/edgexfoundry/export/registration/ExportClientImpl.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.export.registration;
20 |
21 | import javax.annotation.PostConstruct;
22 | import javax.ws.rs.NotFoundException;
23 |
24 | import org.edgexfoundry.domain.export.ExportDestination;
25 | import org.edgexfoundry.domain.export.ExportFormat;
26 | import org.edgexfoundry.domain.export.ExportRegistration;
27 | import org.edgexfoundry.domain.meta.Addressable;
28 | import org.edgexfoundry.domain.meta.Protocol;
29 | import org.jboss.resteasy.client.jaxrs.ResteasyClient;
30 | import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
31 | import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;
32 | import org.springframework.beans.factory.annotation.Value;
33 | import org.springframework.stereotype.Component;
34 |
35 | @Component
36 | public class ExportClientImpl implements ExportClient {
37 |
38 | private static final org.edgexfoundry.support.logging.client.EdgeXLogger logger =
39 | org.edgexfoundry.support.logging.client.EdgeXLoggerFactory
40 | .getEdgeXLogger(ExportClientImpl.class);
41 |
42 | @Value("${export.client}")
43 | private boolean exportClient;
44 |
45 | @Value("${export.client.registration.url}")
46 | private String url;
47 |
48 | @Value("${export.client.registration.name}")
49 | private String clientName;
50 |
51 | @Value("${export.client.registration.retry.time}")
52 | private int retryTime;
53 |
54 | @Value("${export.client.registration.retry.attempts}")
55 | private int retryAttempts;
56 |
57 | @PostConstruct
58 | public void init() throws InterruptedException {
59 | if (exportClient) {
60 | int tries = 0;
61 | do {
62 | tries++;
63 | try {
64 | if (isRegistered()) {
65 | logger.info("Already registered with export service");
66 | return;
67 | }
68 | logger.debug("Attempting to register with export service");
69 | if (registerRulesEngine()) {
70 | logger.info("Export client registration complete");
71 | return;
72 | }
73 | } catch (Exception e) {
74 | logger.debug("Problem while connecting to export client service: " + e.getMessage());
75 | logger.info("Export Client registration try# : " + tries);
76 | }
77 | retrySleep(retryTime);
78 | } while (tries < retryAttempts);
79 | logger.error("Trouble connecting to export service. Exiting.\n");
80 | System.exit(1);
81 | } else
82 | logger.info("Direct receiver of messages from core. No export client registration");
83 | }
84 |
85 | private void retrySleep(int time) throws InterruptedException {
86 | try {
87 | Thread.sleep(time);
88 | } catch (InterruptedException e) {
89 | logger.error("Problem sleeping between registration retries");
90 | throw e;
91 | }
92 | }
93 |
94 | public boolean isRegistered() {
95 | try {
96 | return (exportRegistrationByName(clientName) != null);
97 | } catch (NotFoundException nfE) {
98 | return false;
99 | }
100 | }
101 |
102 | public boolean registerRulesEngine() {
103 | logger.debug("Registering rules engine service as export client");
104 | String id = register(getExportRegistration());
105 | if (id != null && id != "")
106 | return true;
107 | logger.error("Problems registering rules engine service as export client");
108 | return false;
109 | }
110 |
111 | @Override
112 | public ExportRegistration exportRegistrationByName(String name) {
113 | return getClient().exportRegistrationByName(name);
114 | }
115 |
116 | @Override
117 | public String register(ExportRegistration registration) {
118 | return getClient().register(registration);
119 | }
120 |
121 | @Override
122 | public boolean deleteByName(String name) {
123 | try {
124 | return getClient().deleteByName(name);
125 | } catch (javax.ws.rs.NotFoundException notFound) {
126 | return false;
127 | }
128 | }
129 |
130 | @Override
131 | public boolean delete(String id) {
132 | try {
133 | return getClient().delete(id);
134 | } catch (javax.ws.rs.NotFoundException notFound) {
135 | return false;
136 | }
137 | }
138 |
139 | private ExportRegistration getExportRegistration() {
140 | ExportRegistration registration = new ExportRegistration();
141 | registration.setName(clientName);
142 | registration.setFormat(ExportFormat.SERIALIZED);
143 | registration.setDestination(ExportDestination.ZMQ_TOPIC);
144 | registration.setEnable(true);
145 | Addressable addressable =
146 | new Addressable("EdgeXRulesEngineAddressable", Protocol.ZMQ, "", "", 0);
147 | registration.setAddressable(addressable);
148 | return registration;
149 | }
150 |
151 | private ExportClient getClient() {
152 | ResteasyClient client = new ResteasyClientBuilder().build();
153 | ResteasyWebTarget target = client.target(url);
154 | return target.proxy(ExportClient.class);
155 | }
156 |
157 | }
158 |
--------------------------------------------------------------------------------
/src/main/java/org/edgexfoundry/messaging/ZeroMQEventSubscriber.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.messaging;
20 |
21 | import java.io.IOException;
22 |
23 | import org.edgexfoundry.domain.core.Event;
24 | import org.edgexfoundry.engine.RuleEngine;
25 | import org.springframework.beans.factory.annotation.Autowired;
26 | import org.springframework.beans.factory.annotation.Value;
27 | import org.springframework.stereotype.Component;
28 | import org.zeromq.SocketType;
29 | import org.zeromq.ZFrame;
30 | import org.zeromq.ZMQ;
31 | import org.zeromq.ZMsg;
32 |
33 | import com.fasterxml.jackson.core.JsonProcessingException;
34 | import com.fasterxml.jackson.databind.JsonNode;
35 | import com.fasterxml.jackson.databind.ObjectMapper;
36 | import com.google.gson.Gson;
37 |
38 | /**
39 | * Export data message ingestion bean - gets messages out of ZeroMQ from export
40 | * service.
41 | */
42 | @Component
43 | public class ZeroMQEventSubscriber {
44 |
45 | private static final org.edgexfoundry.support.logging.client.EdgeXLogger logger = org.edgexfoundry.support.logging.client.EdgeXLoggerFactory
46 | .getEdgeXLogger(ZeroMQEventSubscriber.class);
47 |
48 | public static final String NO_ENVELOPE = "no_envelope";
49 | public static final String JSON = "application/json";
50 | public static final String CBOR = "application/cbor";
51 | public static final String CONTENT_TYPE = "ContentType";
52 |
53 | @Value("${export.zeromq.port}")
54 | private String zeromqAddressPort;
55 | @Value("${export.zeromq.host}")
56 | private String zeromqAddress;
57 | @Value("${export.client}")
58 | private boolean exportClient;
59 | @Value("${expect.serializedjava}")
60 | private boolean serializedJava;
61 |
62 | @Autowired
63 | RuleEngine engine;
64 |
65 | private ZMQ.Socket subscriber;
66 | private ZMQ.Context context;
67 | private ObjectMapper mapper = new ObjectMapper();
68 |
69 | {
70 | context = ZMQ.context(1);
71 | }
72 |
73 | public void receive() {
74 | getSubscriber();
75 | JsonNode node;
76 | ZMsg zmsg;
77 | ZFrame[] parts;
78 | logger.info("Watching for new exported Event messages...");
79 | try {
80 | while (!Thread.currentThread().isInterrupted()) {
81 | zmsg = ZMsg.recvMsg(subscriber);
82 | parts = new ZFrame[zmsg.size()];
83 | zmsg.toArray(parts);
84 | logger.debug("Message has " + parts.length + " parts.");
85 |
86 | if (parts.length < 2) {// if the message is not a multi-part message
87 | try {
88 | node = mapper.readTree(parts[0].getData());
89 | } catch (JsonProcessingException jsonE) { // if can't parse the data from the message, assume it is CBOR
90 | processCborEvent(parts[0]);
91 | break;
92 | }
93 | } else // if the message is multi-part message
94 | node = mapper.readTree(parts[1].getData());
95 | switch (payloadType(node)) {
96 | case NO_ENVELOPE:
97 | processEvent(node);
98 | break;
99 | case JSON:
100 | processJsonEvent(node);
101 | break;
102 | case CBOR:
103 | processCborEvent(node);
104 | break;
105 | default:
106 | logger.error("Unknown payload type received");
107 | break;
108 | }
109 | }
110 | } catch (Exception e) {
111 | logger.error("Unable to receive messages via ZMQ: " + e.getMessage());
112 | }
113 | logger.error("Shutting off Event message watch due to error!");
114 | if (subscriber != null)
115 | subscriber.close();
116 | subscriber = null;
117 | // try to restart
118 | logger.debug("Attempting restart of Event message watch.");
119 |
120 | receive();
121 |
122 | }
123 |
124 | private String payloadType(JsonNode node) throws JsonProcessingException, IOException {
125 | JsonNode contentType = node.get(CONTENT_TYPE);
126 | if (contentType == null)
127 | return NO_ENVELOPE;
128 | else
129 | return node.get(CONTENT_TYPE).asText();
130 | }
131 |
132 | public String getZeromqAddress() {
133 | return zeromqAddress;
134 | }
135 |
136 | public void setZeromqAddress(String zeromqAddress) {
137 | this.zeromqAddress = zeromqAddress;
138 | }
139 |
140 | public String getZeromqAddressPort() {
141 | return zeromqAddressPort;
142 | }
143 |
144 | public void setZeromqAddressPort(String zeromqAddressPort) {
145 | this.zeromqAddressPort = zeromqAddressPort;
146 | }
147 |
148 | private ZMQ.Socket getSubscriber() {
149 | if (subscriber == null) {
150 | try {
151 | subscriber = context.socket(SocketType.SUB);
152 | subscriber.connect(zeromqAddress + ":" + zeromqAddressPort);
153 | subscriber.subscribe("".getBytes());
154 | } catch (Exception e) {
155 | logger.error("Unable to get a ZMQ subscriber. Error: " + e);
156 | subscriber = null;
157 | }
158 | }
159 | return subscriber;
160 | }
161 |
162 | private void processJsonEvent(JsonNode node) throws IOException {
163 | logger.info("JSON event received");
164 | Event event = toEvent(node.get("Payload").binaryValue());
165 | logger.debug("Event: " + event);
166 | executeOnEvent(event);
167 | }
168 |
169 | private void processEvent(JsonNode node) {
170 | logger.info("Event received");
171 | Event event = mapper.convertValue(node, Event.class);
172 | logger.debug("Event: " + event);
173 | executeOnEvent(event);
174 | }
175 |
176 | private void executeOnEvent(Event event) {
177 | engine.execute(event);
178 | logger.info("Event sent to rules engine for device id: " + event.getDevice());
179 | }
180 |
181 | private void processCborEvent(Object data) {
182 | logger.info("CBOR received. CBOR is unsupported in the rules engine at this time; message being ignored");
183 | }
184 |
185 | private static Event toEvent(byte[] eventBytes) throws IOException {
186 | Gson gson = new Gson();
187 | String json = new String(eventBytes);
188 | return gson.fromJson(json, Event.class);
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/src/main/java/org/edgexfoundry/rule/domain/Action.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.rule.domain;
20 |
21 | public class Action {
22 |
23 | private String device;
24 | private String command;
25 | private String body;
26 |
27 | public String getDevice() {
28 | return device;
29 | }
30 |
31 | public void setDevice(String device) {
32 | this.device = device;
33 | }
34 |
35 | public String getCommand() {
36 | return command;
37 | }
38 |
39 | public void setCommand(String command) {
40 | this.command = command;
41 | }
42 |
43 | public String getBody() {
44 | return body;
45 | }
46 |
47 | public void setBody(String body) {
48 | this.body = body;
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/org/edgexfoundry/rule/domain/Condition.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.rule.domain;
20 |
21 | import java.util.ArrayList;
22 | import java.util.List;
23 |
24 | public class Condition {
25 |
26 | private String device;
27 | private List checks;
28 |
29 | public String getDevice() {
30 | return device;
31 | }
32 |
33 | public void setDevice(String device) {
34 | this.device = device;
35 | }
36 |
37 | public List getChecks() {
38 | return checks;
39 | }
40 |
41 | public void setChecks(List checks) {
42 | this.checks = checks;
43 | }
44 |
45 | public void addCheck(ValueCheck check) {
46 | if (checks == null)
47 | checks = new ArrayList<>();
48 | checks.add(check);
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/org/edgexfoundry/rule/domain/Rule.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.rule.domain;
20 |
21 | public class Rule {
22 |
23 | private String name;
24 | private Condition condition;
25 | private Action action;
26 | private String log;
27 |
28 | public String getName() {
29 | return name;
30 | }
31 |
32 | public void setName(String name) {
33 | this.name = name;
34 | }
35 |
36 | public Condition getCondition() {
37 | return condition;
38 | }
39 |
40 | public void setCondition(Condition condition) {
41 | this.condition = condition;
42 | }
43 |
44 | public Action getAction() {
45 | return action;
46 | }
47 |
48 | public void setAction(Action action) {
49 | this.action = action;
50 | }
51 |
52 | public String getLog() {
53 | return log;
54 | }
55 |
56 | public void setLog(String log) {
57 | this.log = log;
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/org/edgexfoundry/rule/domain/ValueCheck.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.rule.domain;
20 |
21 | public class ValueCheck {
22 |
23 | private String parameter;
24 | private String operand1;
25 | private String operation;
26 | private String operand2;
27 |
28 | public String getParameter() {
29 | return parameter;
30 | }
31 |
32 | public void setParameter(String parameter) {
33 | this.parameter = parameter;
34 | }
35 |
36 | public String getOperand1() {
37 | return operand1;
38 | }
39 |
40 | public void setOperand1(String operand1) {
41 | this.operand1 = operand1;
42 | }
43 |
44 | public String getOperation() {
45 | return operation;
46 | }
47 |
48 | public void setOperation(String operation) {
49 | this.operation = operation;
50 | }
51 |
52 | public String getOperand2() {
53 | return operand2;
54 | }
55 |
56 | public void setOperand2(String operand2) {
57 | this.operand2 = operand2;
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright 2017 Dell Inc.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | # @microservice: support-rulesengine
17 | # @author: Jim White, Dell
18 | # @version: 1.0.0
19 | ###############################################################################
20 | #-----------------General Config-----------------------------------------------
21 | #every 5 minutes (in milliseconds)
22 | heart.beat.time=300000
23 | #messages
24 | heart.beat.msg=Support Rules Engine data heart beat
25 | app.open.msg=This is the Support Rules Engine Microservice.
26 | # set port (override Spring boot default port 8080 )
27 | server.port=48075
28 | #-----------------App Service Configurable Rules Config----------------------------------------
29 | #Turn on/off registration of rules engine as app-service-configurable client.
30 | #Set to false to receive messages directly from core data
31 | export.client=false
32 | expect.serializedjava=false
33 | export.client.registration.url=http://localhost:48071/api/v1
34 | #export.client.registration.url=http://edgex-export-client:48071/api/v1
35 | export.client.registration.name=EdgeXRulesEngine
36 | #use port 5566 when connected to app-service-configurable
37 | #use port 5563 when connected to core data directly
38 | export.zeromq.port=5566
39 | #export.zeromq.port=5563
40 | export.zeromq.host=tcp://localhost
41 | #export.zeromq.host=tcp://edgex-app-service-configurable-rules
42 | #how long to wait to retry registration
43 | export.client.registration.retry.time=10000
44 | #how many times to try registration before exiting
45 | export.client.registration.retry.attempts=100
46 | #-----------------Logging Config-----------------------------------------------
47 | #logging levels (used to control log4j entries)
48 | logging.level.org.springframework=ERROR
49 | logging.level.org.apache=ERROR
50 | logging.level.org.edgexfoundry=INFO
51 | #log files are rotated after 10MB by default in Spring boot
52 | logging.file=edgex-support-rulesengine.log
53 | #print stack traces with errors on REST calls
54 | print.stacktrace=true
55 | #-----------------Drools Config-----------------------------------------------
56 | #Drools drl resource path
57 | rules.default.path=edgex/rules
58 | #rules.default.path=/edgex/edgex-support-rulesengine/rules
59 | rules.packagename=org.edgexfoundry.rules
60 | rules.fileextension=.drl
61 | rules.template.path=./src/main/resources
62 | #rules.template.path=edgex/templates
63 | #rules.template.path=/edgex/edgex-support-rulesengine/templates
64 | rules.template.name=rule-template.drl
65 | rules.template.encoding=UTF-8
66 | #IOT core data database service connection information
67 | core.db.command.url=http://localhost:48082/api/v1/device
68 | #core.db.command.url=http://edgex-core-command:48082/api/v1/device
69 | #IOT metadata database service connection information
70 | meta.db.addressable.url=http://localhost:48081/api/v1/addressable
71 | meta.db.deviceservice.url=http://localhost:48081/api/v1/deviceservice
72 | meta.db.deviceprofile.url=http://localhost:48081/api/v1/deviceprofile
73 | meta.db.device.url=http://localhost:48081/api/v1/device
74 | meta.db.devicereport.url=http://localhost:48081/api/v1/devicereport
75 | meta.db.command.url=http://localhost:48081/api/v1/command
76 | meta.db.event.url=http://localhost:48081/api/v1/event
77 | meta.db.schedule.url=http://localhost:48081/api/v1/schedule
78 | meta.db.provisionwatcher.url=http://localhost:48081/api/v1/provisionwatcher
79 | #meta.db.addressable.url=http://edgex-core-metadata:48081/api/v1/addressable
80 | #meta.db.deviceservice.url=http://edgex-core-metadata:48081/api/v1/deviceservice
81 | #meta.db.deviceprofile.url=http://edgex-core-metadata:48081/api/v1/deviceprofile
82 | #meta.db.device.url=http://edgex-core-metadata:48081/api/v1/device
83 | #meta.db.devicereport.url=http://edgex-core-metadata:48081/api/v1/devicereport
84 | #meta.db.command.url=http://edgex-core-metadata:48081/api/v1/command
85 | #meta.db.event.url=http://edgex-core-metadata:48081/api/v1/event
86 | #meta.db.schedule.url=http://edgex-core-metadata:48081/api/v1/schedule
87 | #meta.db.provisionwatcher.url=http://edgex-core-metadata:48081/api/v1/provisionwatcher
88 | #-----------------Remote Logging Config------------------------------------------
89 | logging.remote.enable=false
90 | logging.remote.url=http://localhost:48061/api/v1/logs
91 | #logging.remote.url=http://edgex-support-logging:48061/api/v1/logs
92 |
--------------------------------------------------------------------------------
/src/main/resources/banner.txt:
--------------------------------------------------------------------------------
1 | ___ _ __ __ ___ _ ___ _
2 | | __|__| |__ _ ___\ \/ / ___ | _ \_ _| |___ ___ | __|_ _ __ _(_)_ _ ___
3 | | _|/ _` / _` / -_)> < |___| | / || | / -_|_-< | _|| ' \/ _` | | ' \/ -_)
4 | |___\__,_\__, \___/_/\_\ |_|_\\_,_|_\___/__/ |___|_||_\__, |_|_||_\___|
5 | |___/ |___/
6 | /*******************************************************************************
7 | * Copyright 2016-2017, Dell, Inc. All Rights Reserved.
8 | ******************************************************************************/
9 |
--------------------------------------------------------------------------------
/src/main/resources/bootstrap.properties:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright 2017 Dell Inc.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | # @microservice: support-rulesengine
17 | # @author: Jim White, Dell
18 | # @version: 1.0.0
19 | ###############################################################################
20 | spring.application.name=edgex-support-rulesengine
21 | spring.cloud.consul.host=localhost
22 | spring.cloud.consul.config.profileSeparator=;
23 | spring.cloud.consul.enabled=false
24 |
--------------------------------------------------------------------------------
/src/main/resources/rule-template.drl:
--------------------------------------------------------------------------------
1 | package org.edgexfoundry.rules;
2 | global org.edgexfoundry.engine.CommandExecutor executor;
3 | global org.edgexfoundry.support.logging.client.EdgeXLogger logger;
4 | import org.edgexfoundry.domain.core.Event;
5 | import org.edgexfoundry.domain.core.Reading;
6 | import java.util.Map;
7 | rule "${rulename}"
8 | when
9 | $e:Event($rlist: readings && device=="${conddeviceid}")
10 | <#if valuechecks??>
11 | <#assign idx = 0>
12 | <#list valuechecks as valuecheck>
13 | $r${idx}:Reading(name=="${valuecheck.parameter}" && ${valuecheck.operand1} ${valuecheck.operation} ${valuecheck.operand2}) from $rlist
14 | <#assign idx = idx + 1>
15 | #list>
16 | #if>
17 | then
18 | executor.fireCommand("${actiondeviceid}", "${actioncommandid}", "${commandbody}");
19 | logger.info("${log}");
20 | end
--------------------------------------------------------------------------------
/src/test/java/org/edgexfoundry/controller/PingControllerTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.controller;
20 |
21 | import static org.junit.Assert.assertEquals;
22 |
23 | import org.edgexfoundry.controller.impl.PingControllerImpl;
24 | import org.edgexfoundry.test.category.RequiresNone;
25 | import org.junit.Before;
26 | import org.junit.Test;
27 | import org.junit.experimental.categories.Category;
28 |
29 | @Category(RequiresNone.class)
30 | public class PingControllerTest {
31 |
32 | private static final String PING_RESP = "pong";
33 |
34 | private PingControllerImpl controller;
35 |
36 | @Before
37 | public void setup() {
38 | controller = new PingControllerImpl();
39 | }
40 |
41 | @Test
42 | public void testPing() {
43 | assertEquals("Ping controller ping test responded incorrectly", PING_RESP, controller.ping());
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/test/java/org/edgexfoundry/controller/RuleEngineControllerTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.controller;
20 |
21 | import static org.junit.Assert.assertEquals;
22 | import static org.junit.Assert.assertTrue;
23 |
24 | import java.io.IOException;
25 | import java.util.ArrayList;
26 | import java.util.List;
27 |
28 | import org.edgexfoundry.controller.impl.RuleEngineControllerImpl;
29 | import org.edgexfoundry.engine.RuleCreator;
30 | import org.edgexfoundry.engine.RuleEngine;
31 | import org.edgexfoundry.exception.controller.ServiceException;
32 | import org.edgexfoundry.rule.domain.Rule;
33 | import org.edgexfoundry.rule.domain.data.RuleData;
34 | import org.edgexfoundry.test.category.RequiresNone;
35 | import org.junit.Before;
36 | import org.junit.Test;
37 | import org.junit.experimental.categories.Category;
38 | import org.mockito.InjectMocks;
39 | import org.mockito.Mock;
40 | import org.mockito.Mockito;
41 | import org.mockito.MockitoAnnotations;
42 |
43 | import freemarker.template.TemplateException;
44 |
45 | @Category({RequiresNone.class})
46 | public class RuleEngineControllerTest {
47 |
48 | private static final String TEST_RULE1 = "Rule1";
49 | private static final String TEST_RULE2 = "Rule2";
50 |
51 | @InjectMocks
52 | private RuleEngineControllerImpl controller;
53 |
54 | @Mock
55 | private RuleEngine engine;
56 |
57 | @Mock
58 | private RuleCreator creator;
59 |
60 |
61 | @Before
62 | public void setup() {
63 | MockitoAnnotations.initMocks(this);
64 | }
65 |
66 | @Test
67 | public void testGetRuleNames() {
68 | List ruleNames = new ArrayList<>();
69 | ruleNames.add(TEST_RULE1);
70 | ruleNames.add(TEST_RULE2);
71 | Mockito.when(engine.getRulenames()).thenReturn(ruleNames);
72 | assertEquals("Rule names not returned as expected", ruleNames, controller.ruleNames());
73 | }
74 |
75 | @Test(expected = ServiceException.class)
76 | public void testGetRuleNamesException() {
77 | Mockito.when(engine.getRulenames()).thenThrow(new RuntimeException());
78 | controller.ruleNames();
79 | }
80 |
81 | @Test
82 | public void testAddRule() {
83 | assertTrue("Rule was not added as expected", controller.addRule(RuleData.newTestInstance()));
84 | }
85 |
86 | @Test(expected = ServiceException.class)
87 | public void testAddRuleException() throws TemplateException, IOException {
88 | Rule rule = RuleData.newTestInstance();
89 | Mockito.when(creator.createDroolRule(rule)).thenThrow(new RuntimeException());
90 | controller.addRule(rule);
91 | }
92 |
93 | @Test
94 | public void testRemoveRule() {
95 | assertTrue("Rule was not removed as expected", controller.removeRule(TEST_RULE1));
96 | }
97 |
98 | @Test(expected = ServiceException.class)
99 | public void testRemoveRuleException() throws IOException {
100 | Mockito.when(engine.removeRule(TEST_RULE1)).thenThrow(new RuntimeException());
101 | controller.removeRule(TEST_RULE1);
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/test/java/org/edgexfoundry/controller/integration/RuleEngineControllerTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.controller.integration;
20 |
21 | import static org.junit.Assert.assertEquals;
22 | import static org.junit.Assert.assertTrue;
23 |
24 | import java.io.IOException;
25 | import java.lang.reflect.Field;
26 | import java.nio.file.Files;
27 | import java.nio.file.Paths;
28 | import java.util.List;
29 |
30 | import org.edgexfoundry.Application;
31 | import org.edgexfoundry.controller.impl.RuleEngineControllerImpl;
32 | import org.edgexfoundry.engine.RuleEngine;
33 | import org.edgexfoundry.exception.controller.ServiceException;
34 | import org.edgexfoundry.rule.domain.Action;
35 | import org.edgexfoundry.rule.domain.Condition;
36 | import org.edgexfoundry.test.category.RequiresExportClientRunning;
37 | import org.edgexfoundry.test.category.RequiresMongoDB;
38 | import org.edgexfoundry.test.category.RequiresSpring;
39 | import org.edgexfoundry.test.category.RequiresWeb;
40 | import org.junit.After;
41 | import org.junit.Before;
42 | import org.junit.Test;
43 | import org.junit.experimental.categories.Category;
44 | import org.junit.runner.RunWith;
45 | import org.springframework.beans.factory.annotation.Autowired;
46 | import org.springframework.boot.test.SpringApplicationConfiguration;
47 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
48 | import org.springframework.test.context.web.WebAppConfiguration;
49 |
50 | /**
51 | * note: Make sure the /edgex/rules folder contains no drl files (or just the testname.drl file)
52 | * before starting this test
53 | */
54 | @RunWith(SpringJUnit4ClassRunner.class)
55 | @SpringApplicationConfiguration(classes = Application.class)
56 | @WebAppConfiguration("src/test/resources")
57 | @Category({RequiresSpring.class, RequiresWeb.class, RequiresMongoDB.class,
58 | RequiresExportClientRunning.class})
59 | public class RuleEngineControllerTest {
60 |
61 | private static final String TEST_RULE_NAME = "testname";
62 |
63 | private static final String TEST_LOG = "testlog";
64 | private static final String TEST_NAME = "testname";
65 | private static final String TEST_BODY = "testbody";
66 | private static final String TEST_CMD = "testcommand";
67 | private static final String TEST_DEVICE = "testdevice";
68 |
69 | @Autowired
70 | RuleEngineControllerImpl controller;
71 |
72 | @Autowired
73 | RuleEngine engine;
74 |
75 | @Before
76 | public void setup() throws IOException {
77 | String ruleContent = new String(Files.readAllBytes(Paths.get("./src/test/resources/rule.txt")));
78 | engine.addRule(ruleContent, TEST_RULE_NAME);
79 | }
80 |
81 | @After
82 | public void cleanup() throws Exception {
83 | Class> clazz = controller.getClass();
84 | Field eng = clazz.getDeclaredField("engine");
85 | eng.setAccessible(true);
86 | eng.set(controller, engine);
87 |
88 | List names = engine.getRulenames();
89 | for (String name : names) {
90 | engine.removeRule(name);
91 | }
92 | }
93 |
94 | @Test
95 | public void testGetRuleNames() throws Exception {
96 | List names = controller.ruleNames();
97 | assertEquals("Rule names not returning list with rule name", 1, names.size());
98 | assertEquals("Rule name not in list of rule names", TEST_RULE_NAME, names.get(0));
99 | }
100 |
101 | @Test(expected = ServiceException.class)
102 | public void testGetRuleNamesException() throws Exception {
103 | Class> clazz = controller.getClass();
104 | Field eng = clazz.getDeclaredField("engine");
105 | eng.setAccessible(true);
106 | eng.set(controller, null);
107 | controller.ruleNames();
108 | }
109 |
110 | @Test
111 | public void testAddRule() {
112 | assertTrue("New rule did not get added correctly", controller.addRule(createRule()));
113 | }
114 |
115 | @Test(expected = ServiceException.class)
116 | public void testAddRuleException() throws Exception {
117 | Class> clazz = controller.getClass();
118 | Field eng = clazz.getDeclaredField("engine");
119 | eng.setAccessible(true);
120 | eng.set(controller, null);
121 | controller.addRule(createRule());
122 | }
123 |
124 | @Test
125 | public void testRemoveRule() {
126 | assertTrue("Rule did not get removed correctly", controller.removeRule(TEST_RULE_NAME));
127 | }
128 |
129 | @Test(expected = ServiceException.class)
130 | public void testRemoveRuleException() throws Exception {
131 | Class> clazz = controller.getClass();
132 | Field eng = clazz.getDeclaredField("engine");
133 | eng.setAccessible(true);
134 | eng.set(controller, null);
135 | controller.removeRule(TEST_RULE_NAME);
136 | }
137 |
138 | private org.edgexfoundry.rule.domain.Rule createRule() {
139 | org.edgexfoundry.rule.domain.Rule rule = new org.edgexfoundry.rule.domain.Rule();
140 | rule.setLog(TEST_LOG);
141 | rule.setName(TEST_NAME);
142 | Action action = new Action();
143 | action.setBody(TEST_BODY);
144 | action.setCommand(TEST_CMD);
145 | action.setDevice(TEST_DEVICE);
146 | rule.setAction(action);
147 | Condition cond = new Condition();
148 | cond.setDevice(TEST_DEVICE);
149 | rule.setCondition(cond);
150 | return rule;
151 | }
152 |
153 | }
154 |
--------------------------------------------------------------------------------
/src/test/java/org/edgexfoundry/engine/CommandExecutorTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.engine;
20 |
21 | import org.apache.commons.lang3.reflect.FieldUtils;
22 | import org.edgexfoundry.controller.CmdClient;
23 | import org.edgexfoundry.test.category.RequiresNone;
24 | import org.junit.Before;
25 | import org.junit.Test;
26 | import org.junit.experimental.categories.Category;
27 | import org.mockito.InjectMocks;
28 | import org.mockito.Mock;
29 | import org.mockito.Mockito;
30 | import org.mockito.MockitoAnnotations;
31 |
32 | @Category(RequiresNone.class)
33 | public class CommandExecutorTest {
34 |
35 | private static final String TEST_DEVICE = "test_device_id";
36 | private static final String TEST_CMD = "test_command_id";
37 | private static final String TEST_BODY = "test body";
38 |
39 | @InjectMocks
40 | private CommandExecutor executor;
41 |
42 | @Mock
43 | private CmdClient client;
44 |
45 | @Before
46 | public void setup() {
47 | MockitoAnnotations.initMocks(this);
48 | }
49 |
50 | @Test
51 | public void testFireCommand() {
52 | executor.fireCommand(TEST_DEVICE, TEST_CMD, TEST_BODY);
53 | }
54 |
55 | @Test
56 | public void testFireCommandException() {
57 | Mockito.when(client.put(TEST_DEVICE, TEST_CMD, TEST_BODY)).thenThrow(new RuntimeException());
58 | executor.fireCommand(TEST_DEVICE, TEST_CMD, TEST_BODY);
59 | }
60 |
61 | @Test
62 | public void testFireCommandNoClient() throws IllegalAccessException {
63 | FieldUtils.writeField(executor, "client", null, true);
64 | executor.fireCommand(TEST_DEVICE, TEST_CMD, TEST_BODY);
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/src/test/java/org/edgexfoundry/engine/RuleCreatorTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.engine;
20 |
21 | import static org.junit.Assert.assertEquals;
22 |
23 | import java.io.IOException;
24 | import java.nio.file.Files;
25 | import java.nio.file.Paths;
26 |
27 | import org.apache.commons.lang3.reflect.FieldUtils;
28 | import org.edgexfoundry.rule.domain.Rule;
29 | import org.edgexfoundry.rule.domain.data.RuleData;
30 | import org.edgexfoundry.test.category.RequiresNone;
31 | import org.junit.Before;
32 | import org.junit.Test;
33 | import org.junit.experimental.categories.Category;
34 | import org.mockito.InjectMocks;
35 | import org.mockito.MockitoAnnotations;
36 |
37 | import freemarker.template.TemplateException;
38 |
39 | @Category(RequiresNone.class)
40 | public class RuleCreatorTest {
41 |
42 | private static final String FIELD_LOC = "templateLocation";
43 | private static final String FIELD_NAME = "templateName";
44 | private static final String FIELD_ENC = "templateEncoding";
45 | private static final String TEMP_LOC = "./src/test/resources";
46 | private static final String TEMP_NAME = "rule-template.drl";
47 | private static final String TEMP_ENC = "UTF-8";
48 |
49 | @InjectMocks
50 | private RuleCreator creator;
51 |
52 | private Rule rule;
53 |
54 | @Before
55 | public void setup() throws IllegalAccessException, IOException {
56 | MockitoAnnotations.initMocks(this);
57 | FieldUtils.writeField(creator, FIELD_LOC, TEMP_LOC, true);
58 | FieldUtils.writeField(creator, FIELD_NAME, TEMP_NAME, true);
59 | FieldUtils.writeField(creator, FIELD_ENC, TEMP_ENC, true);
60 | creator.init();
61 | rule = RuleData.newTestInstance();
62 | }
63 |
64 | @Test(expected = IOException.class)
65 | public void testInitException() throws NoSuchFieldException, SecurityException,
66 | IllegalArgumentException, IllegalAccessException, IOException {
67 | FieldUtils.writeField(creator, FIELD_LOC, "foobar", true);
68 | creator.init();
69 | }
70 |
71 | @Test
72 | public void testCreateDroolRule() throws TemplateException, IOException {
73 | String ruleContent = new String(Files.readAllBytes(Paths.get("./src/test/resources/rule.txt")));
74 | assertEquals("Drool file not created properly", ruleContent, creator.createDroolRule(rule));
75 | }
76 |
77 | @Test(expected = IOException.class)
78 | public void testCreateDroolRuleIOException()
79 | throws IllegalAccessException, TemplateException, IOException {
80 | FieldUtils.writeField(creator, FIELD_NAME, "foobar", true);
81 | creator.createDroolRule(rule);
82 | }
83 |
84 | @Test(expected = TemplateException.class)
85 | public void testCreateDroolRuleTemplateException() throws TemplateException, IOException,
86 | NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
87 | rule.getAction().setDevice(null);
88 | creator.createDroolRule(rule);
89 | }
90 |
91 | @Test(expected = Exception.class)
92 | public void testCreateDroolRuleException()
93 | throws IllegalAccessException, TemplateException, IOException {
94 | FieldUtils.writeField(creator, "cfg", null, true);
95 | creator.createDroolRule(rule);
96 | }
97 |
98 | }
99 |
--------------------------------------------------------------------------------
/src/test/java/org/edgexfoundry/engine/RunEngineTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.engine;
20 |
21 | import org.apache.commons.lang3.reflect.FieldUtils;
22 | import org.edgexfoundry.test.category.RequiresNone;
23 | import org.junit.Before;
24 | import org.junit.experimental.categories.Category;
25 | import org.mockito.InjectMocks;
26 | import org.mockito.Mock;
27 | import org.mockito.MockitoAnnotations;
28 |
29 | @Category({RequiresNone.class})
30 | public class RunEngineTest {
31 |
32 | private static final String TEST_RESOURCE_FILE_PATH = "./src/test/resources";
33 | private static final String TEST_PACKAGE_NAME ="org.edgexfoundry.rules";
34 | private static final String TEST_RULE_FILE_EXT=".drl";
35 |
36 | @InjectMocks
37 | private RuleEngine engine;
38 |
39 | @Mock
40 | private CommandExecutor executor;
41 |
42 | @Before
43 | public void setup() throws IllegalAccessException {
44 | MockitoAnnotations.initMocks(this);
45 | FieldUtils.writeField(engine, "resourceFilePath", TEST_RESOURCE_FILE_PATH, true);
46 | FieldUtils.writeField(engine, "packageName", TEST_PACKAGE_NAME, true);
47 | FieldUtils.writeField(engine, "ruleFileExtension", TEST_RULE_FILE_EXT, true);
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/test/java/org/edgexfoundry/engine/integration/RuleEngineTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.engine.integration;
20 |
21 | import static org.junit.Assert.assertEquals;
22 | import static org.junit.Assert.assertTrue;
23 |
24 | import java.io.IOException;
25 | import java.nio.file.Files;
26 | import java.nio.file.Paths;
27 | import java.util.List;
28 |
29 | import org.edgexfoundry.Application;
30 | import org.edgexfoundry.domain.core.Event;
31 | import org.edgexfoundry.engine.RuleEngine;
32 | import org.edgexfoundry.test.category.RequiresExportClientRunning;
33 | import org.edgexfoundry.test.category.RequiresMongoDB;
34 | import org.edgexfoundry.test.category.RequiresSpring;
35 | import org.edgexfoundry.test.category.RequiresWeb;
36 | import org.edgexfoundry.test.data.EventData;
37 | import org.junit.After;
38 | import org.junit.Before;
39 | import org.junit.Test;
40 | import org.junit.experimental.categories.Category;
41 | import org.junit.runner.RunWith;
42 | import org.springframework.beans.factory.annotation.Autowired;
43 | import org.springframework.boot.test.SpringApplicationConfiguration;
44 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
45 | import org.springframework.test.context.web.WebAppConfiguration;
46 |
47 | /**
48 | * note: Make sure the /edgex/rules folder contains no drl files (or just the testname.drl file)
49 | * before starting this test
50 | */
51 | @RunWith(SpringJUnit4ClassRunner.class)
52 | @SpringApplicationConfiguration(classes = Application.class)
53 | @WebAppConfiguration("src/test/resources")
54 | @Category({RequiresSpring.class, RequiresWeb.class, RequiresMongoDB.class,
55 | RequiresExportClientRunning.class})
56 | public class RuleEngineTest {
57 |
58 | private static final String TEST_RULE_NAME = "testname";
59 | private String ruleContent;
60 |
61 | @Autowired
62 | private RuleEngine engine;
63 |
64 | @Before
65 | public void setup() throws IOException {
66 | ruleContent = new String(Files.readAllBytes(Paths.get("./src/test/resources/rule.txt")));
67 | engine.addRule(ruleContent, TEST_RULE_NAME);
68 | }
69 |
70 | @After
71 | public void cleanup() throws Exception {
72 | List names = engine.getRulenames();
73 | for (String name : names) {
74 | engine.removeRule(name);
75 | }
76 | }
77 |
78 | @Test
79 | public void testAddRule() throws Exception {
80 | engine.addRule(ruleContent, TEST_RULE_NAME);
81 | String droolfile = engine.getResourceFilePath() + "/" + TEST_RULE_NAME + ".drl";
82 | String content = new String(Files.readAllBytes(Paths.get(droolfile)));
83 | assertTrue("Rule did not get added properly", content.length() > 1);
84 | }
85 |
86 | @Test
87 | public void testRemoveRule() throws IOException {
88 | engine.removeRule(TEST_RULE_NAME);
89 | String droolfile = engine.getResourceFilePath() + "/" + TEST_RULE_NAME + ".drl";
90 | String content = new String(Files.readAllBytes(Paths.get(droolfile)));
91 | assertTrue("Rule did not get removed properly", content.length() == 0);
92 | }
93 |
94 | @Test
95 | public void testGetRuleNames() throws Exception {
96 | assertTrue("No rules should exist", !engine.getRulenames().isEmpty());
97 | assertEquals("Existing rule name not found", TEST_RULE_NAME, engine.getRulenames().get(0));
98 | }
99 |
100 | @Test
101 | public void testExcecute() {
102 | Event event = EventData.newTestInstance();
103 | engine.execute(event);
104 | }
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/src/test/java/org/edgexfoundry/export/registration/integration/web/ExportClientImplTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.export.registration.integration.web;
20 |
21 | import static org.junit.Assert.assertFalse;
22 | import static org.junit.Assert.assertNotNull;
23 | import static org.junit.Assert.assertNull;
24 | import static org.junit.Assert.assertTrue;
25 |
26 | import org.edgexfoundry.Application;
27 | import org.edgexfoundry.domain.export.ExportFormat;
28 | import org.edgexfoundry.domain.export.ExportRegistration;
29 | import org.edgexfoundry.domain.meta.Addressable;
30 | import org.edgexfoundry.domain.meta.Protocol;
31 | import org.edgexfoundry.export.registration.ExportClientImpl;
32 | import org.edgexfoundry.test.category.RequiresExportClientRunning;
33 | import org.edgexfoundry.test.category.RequiresMongoDB;
34 | import org.edgexfoundry.test.category.RequiresSpring;
35 | import org.edgexfoundry.test.category.RequiresWeb;
36 | import org.junit.Test;
37 | import org.junit.experimental.categories.Category;
38 | import org.junit.runner.RunWith;
39 | import org.springframework.beans.factory.annotation.Autowired;
40 | import org.springframework.beans.factory.annotation.Value;
41 | import org.springframework.boot.test.SpringApplicationConfiguration;
42 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
43 | import org.springframework.test.context.web.WebAppConfiguration;
44 |
45 | @RunWith(SpringJUnit4ClassRunner.class)
46 | @SpringApplicationConfiguration(classes = Application.class)
47 | @WebAppConfiguration("src/test/resources")
48 | @Category({RequiresSpring.class, RequiresWeb.class, RequiresMongoDB.class,
49 | RequiresExportClientRunning.class})
50 | public class ExportClientImplTest {
51 |
52 | private static final String TEST_CLIENT_NAME = "testclient";
53 | private static final ExportFormat TEST_FORMAT = ExportFormat.SERIALIZED;
54 | private static final boolean TEST_ENABLE = true;
55 | private static final Addressable TEST_ADDR =
56 | new Addressable("testaddress", Protocol.ZMQ, "", "", 0);
57 |
58 | @Autowired
59 | private ExportClientImpl client;
60 |
61 | @Value("${export.client.registration.name}")
62 | private String clientName;
63 |
64 | @Test
65 | public void testIsRegistered() {
66 | assertTrue(client.isRegistered());
67 | }
68 |
69 | @Test
70 | public void testRegisterRulesEngine() {
71 | assertTrue(client.deleteByName(clientName));
72 | assertTrue(client.registerRulesEngine());
73 | }
74 |
75 | @Test
76 | public void testExportRegistrationByNameNoneFound() {
77 | assertNull(client.exportRegistrationByName("foo"));
78 | }
79 |
80 | @Test
81 | public void testExportRegistrationByName() {
82 | assertNotNull(client.exportRegistrationByName(clientName));
83 | }
84 |
85 | @Test
86 | // also tests delete by id
87 | public void testRegister() {
88 | String id = client.register(newInstance());
89 | assertNotNull(id);
90 | assertTrue(client.delete(id));
91 | }
92 |
93 | @Test
94 | public void testDeleteByIdNoneFound() {
95 | assertFalse(client.delete("foobar"));
96 | }
97 |
98 | @Test
99 | public void testDeleteByName() {
100 | client.register(newInstance());
101 | assertTrue(client.deleteByName(TEST_CLIENT_NAME));
102 | }
103 |
104 | @Test
105 | public void testDeleteByNameNotFound() {
106 | assertFalse(client.deleteByName("foo"));
107 | }
108 |
109 | private ExportRegistration newInstance() {
110 | ExportRegistration registration = new ExportRegistration();
111 | registration.setName(TEST_CLIENT_NAME);
112 | registration.setFormat(TEST_FORMAT);
113 | registration.setEnable(TEST_ENABLE);
114 | registration.setAddressable(TEST_ADDR);
115 | return registration;
116 | }
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/src/test/java/org/edgexfoundry/export/registration/integration/web/LocalErrorControllerTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.export.registration.integration.web;
20 |
21 | import static org.junit.Assert.assertEquals;
22 |
23 | import org.edgexfoundry.Application;
24 | import org.edgexfoundry.controller.impl.LocalErrorController;
25 | import org.edgexfoundry.test.category.RequiresExportClientRunning;
26 | import org.edgexfoundry.test.category.RequiresMongoDB;
27 | import org.edgexfoundry.test.category.RequiresSpring;
28 | import org.edgexfoundry.test.category.RequiresWeb;
29 | import org.junit.Before;
30 | import org.junit.Test;
31 | import org.junit.experimental.categories.Category;
32 | import org.junit.runner.RunWith;
33 | import org.springframework.beans.factory.annotation.Autowired;
34 | import org.springframework.boot.test.SpringApplicationConfiguration;
35 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
36 | import org.springframework.test.context.web.WebAppConfiguration;
37 |
38 | @RunWith(SpringJUnit4ClassRunner.class)
39 | @SpringApplicationConfiguration(classes = Application.class)
40 | @WebAppConfiguration("src/test/resources")
41 | @Category({RequiresSpring.class, RequiresWeb.class, RequiresMongoDB.class,
42 | RequiresExportClientRunning.class})
43 | public class LocalErrorControllerTest {
44 |
45 | @Autowired
46 | private LocalErrorController controller;
47 |
48 | @Before
49 | public void setup() {
50 | // controller = new LocalErrorController();
51 | }
52 |
53 | @Test
54 | public void testGetErrorPath() {
55 | assertEquals("/error", controller.getErrorPath());
56 | }
57 |
58 | @Test
59 | public void testError() {
60 | TestHttpServletRequest request = new TestHttpServletRequest();
61 | TestHttpServletResponse response = new TestHttpServletResponse();
62 | controller.error(request, response);
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/src/test/java/org/edgexfoundry/export/registration/integration/web/TestHttpServletRequest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.export.registration.integration.web;
20 |
21 | import java.io.BufferedReader;
22 | import java.io.IOException;
23 | import java.io.UnsupportedEncodingException;
24 | import java.security.Principal;
25 | import java.util.Collection;
26 | import java.util.Enumeration;
27 | import java.util.Locale;
28 | import java.util.Map;
29 |
30 | import javax.servlet.AsyncContext;
31 | import javax.servlet.DispatcherType;
32 | import javax.servlet.RequestDispatcher;
33 | import javax.servlet.ServletContext;
34 | import javax.servlet.ServletException;
35 | import javax.servlet.ServletInputStream;
36 | import javax.servlet.ServletRequest;
37 | import javax.servlet.ServletResponse;
38 | import javax.servlet.http.Cookie;
39 | import javax.servlet.http.HttpServletRequest;
40 | import javax.servlet.http.HttpServletResponse;
41 | import javax.servlet.http.HttpSession;
42 | import javax.servlet.http.HttpUpgradeHandler;
43 | import javax.servlet.http.Part;
44 |
45 | public class TestHttpServletRequest implements HttpServletRequest {
46 |
47 | @Override
48 | public AsyncContext getAsyncContext() {
49 | return null;
50 | }
51 |
52 | @Override
53 | public Object getAttribute(String arg0) {
54 | return null;
55 | }
56 |
57 | @Override
58 | public Enumeration getAttributeNames() {
59 | return null;
60 | }
61 |
62 | @Override
63 | public String getCharacterEncoding() {
64 | return null;
65 | }
66 |
67 | @Override
68 | public int getContentLength() {
69 | return 0;
70 | }
71 |
72 | @Override
73 | public long getContentLengthLong() {
74 | return 0;
75 | }
76 |
77 | @Override
78 | public String getContentType() {
79 | return null;
80 | }
81 |
82 | @Override
83 | public DispatcherType getDispatcherType() {
84 | return null;
85 | }
86 |
87 | @Override
88 | public ServletInputStream getInputStream() throws IOException {
89 | return null;
90 | }
91 |
92 | @Override
93 | public String getLocalAddr() {
94 | return null;
95 | }
96 |
97 | @Override
98 | public String getLocalName() {
99 | return null;
100 | }
101 |
102 | @Override
103 | public int getLocalPort() {
104 | return 0;
105 | }
106 |
107 | @Override
108 | public Locale getLocale() {
109 | return null;
110 | }
111 |
112 | @Override
113 | public Enumeration getLocales() {
114 | return null;
115 | }
116 |
117 | @Override
118 | public String getParameter(String arg0) {
119 | return null;
120 | }
121 |
122 | @Override
123 | public Map getParameterMap() {
124 | return null;
125 | }
126 |
127 | @Override
128 | public Enumeration getParameterNames() {
129 | return null;
130 | }
131 |
132 | @Override
133 | public String[] getParameterValues(String arg0) {
134 | return null;
135 | }
136 |
137 | @Override
138 | public String getProtocol() {
139 | return null;
140 | }
141 |
142 | @Override
143 | public BufferedReader getReader() throws IOException {
144 | return null;
145 | }
146 |
147 | @Override
148 | public String getRealPath(String arg0) {
149 | return null;
150 | }
151 |
152 | @Override
153 | public String getRemoteAddr() {
154 | return null;
155 | }
156 |
157 | @Override
158 | public String getRemoteHost() {
159 | return null;
160 | }
161 |
162 | @Override
163 | public int getRemotePort() {
164 | return 0;
165 | }
166 |
167 | @Override
168 | public RequestDispatcher getRequestDispatcher(String arg0) {
169 | return null;
170 | }
171 |
172 | @Override
173 | public String getScheme() {
174 | return null;
175 | }
176 |
177 | @Override
178 | public String getServerName() {
179 | return null;
180 | }
181 |
182 | @Override
183 | public int getServerPort() {
184 | return 0;
185 | }
186 |
187 | @Override
188 | public ServletContext getServletContext() {
189 | return null;
190 | }
191 |
192 | @Override
193 | public boolean isAsyncStarted() {
194 | return false;
195 | }
196 |
197 | @Override
198 | public boolean isAsyncSupported() {
199 | return false;
200 | }
201 |
202 | @Override
203 | public boolean isSecure() {
204 | return false;
205 | }
206 |
207 | @Override
208 | public void removeAttribute(String arg0) {
209 |
210 | }
211 |
212 | @Override
213 | public void setAttribute(String arg0, Object arg1) {
214 |
215 | }
216 |
217 | @Override
218 | public void setCharacterEncoding(String arg0) throws UnsupportedEncodingException {
219 |
220 | }
221 |
222 | @Override
223 | public AsyncContext startAsync() throws IllegalStateException {
224 | return null;
225 | }
226 |
227 | @Override
228 | public AsyncContext startAsync(ServletRequest arg0, ServletResponse arg1)
229 | throws IllegalStateException {
230 | return null;
231 | }
232 |
233 | @Override
234 | public boolean authenticate(HttpServletResponse arg0) throws IOException, ServletException {
235 | return false;
236 | }
237 |
238 | @Override
239 | public String changeSessionId() {
240 | return null;
241 | }
242 |
243 | @Override
244 | public String getAuthType() {
245 | return null;
246 | }
247 |
248 | @Override
249 | public String getContextPath() {
250 | return null;
251 | }
252 |
253 | @Override
254 | public Cookie[] getCookies() {
255 | return null;
256 | }
257 |
258 | @Override
259 | public long getDateHeader(String arg0) {
260 | return 0;
261 | }
262 |
263 | @Override
264 | public String getHeader(String arg0) {
265 | return null;
266 | }
267 |
268 | @Override
269 | public Enumeration getHeaderNames() {
270 | return null;
271 | }
272 |
273 | @Override
274 | public Enumeration getHeaders(String arg0) {
275 | return null;
276 | }
277 |
278 | @Override
279 | public int getIntHeader(String arg0) {
280 | return 0;
281 | }
282 |
283 | @Override
284 | public String getMethod() {
285 | return null;
286 | }
287 |
288 | @Override
289 | public Part getPart(String arg0) throws IOException, ServletException {
290 | return null;
291 | }
292 |
293 | @Override
294 | public Collection getParts() throws IOException, ServletException {
295 | return null;
296 | }
297 |
298 | @Override
299 | public String getPathInfo() {
300 | return null;
301 | }
302 |
303 | @Override
304 | public String getPathTranslated() {
305 | return null;
306 | }
307 |
308 | @Override
309 | public String getQueryString() {
310 | return null;
311 | }
312 |
313 | @Override
314 | public String getRemoteUser() {
315 | return null;
316 | }
317 |
318 | @Override
319 | public String getRequestURI() {
320 | return null;
321 | }
322 |
323 | @Override
324 | public StringBuffer getRequestURL() {
325 | return null;
326 | }
327 |
328 | @Override
329 | public String getRequestedSessionId() {
330 | return null;
331 | }
332 |
333 | @Override
334 | public String getServletPath() {
335 | return null;
336 | }
337 |
338 | @Override
339 | public HttpSession getSession() {
340 | return null;
341 | }
342 |
343 | @Override
344 | public HttpSession getSession(boolean arg0) {
345 | return null;
346 | }
347 |
348 | @Override
349 | public Principal getUserPrincipal() {
350 | return null;
351 | }
352 |
353 | @Override
354 | public boolean isRequestedSessionIdFromCookie() {
355 | return false;
356 | }
357 |
358 | @Override
359 | public boolean isRequestedSessionIdFromURL() {
360 | return false;
361 | }
362 |
363 | @Override
364 | public boolean isRequestedSessionIdFromUrl() {
365 | return false;
366 | }
367 |
368 | @Override
369 | public boolean isRequestedSessionIdValid() {
370 | return false;
371 | }
372 |
373 | @Override
374 | public boolean isUserInRole(String arg0) {
375 | return false;
376 | }
377 |
378 | @Override
379 | public void login(String arg0, String arg1) throws ServletException {
380 |
381 | }
382 |
383 | @Override
384 | public void logout() throws ServletException {
385 |
386 | }
387 |
388 | @Override
389 | public T upgrade(Class arg0)
390 | throws IOException, ServletException {
391 | return null;
392 | }
393 |
394 | }
395 |
--------------------------------------------------------------------------------
/src/test/java/org/edgexfoundry/export/registration/integration/web/TestHttpServletResponse.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.export.registration.integration.web;
20 |
21 | import java.io.IOException;
22 | import java.io.PrintWriter;
23 | import java.util.Collection;
24 | import java.util.Locale;
25 |
26 | import javax.servlet.ServletOutputStream;
27 | import javax.servlet.http.Cookie;
28 | import javax.servlet.http.HttpServletResponse;
29 |
30 | public class TestHttpServletResponse implements HttpServletResponse {
31 |
32 | @Override
33 | public void flushBuffer() throws IOException {}
34 |
35 | @Override
36 | public int getBufferSize() {
37 | return 0;
38 | }
39 |
40 | @Override
41 | public String getCharacterEncoding() {
42 | return null;
43 | }
44 |
45 | @Override
46 | public String getContentType() {
47 | return null;
48 | }
49 |
50 | @Override
51 | public Locale getLocale() {
52 | return null;
53 | }
54 |
55 | @Override
56 | public ServletOutputStream getOutputStream() throws IOException {
57 | return null;
58 | }
59 |
60 | @Override
61 | public PrintWriter getWriter() throws IOException {
62 | return null;
63 | }
64 |
65 | @Override
66 | public boolean isCommitted() {
67 | return false;
68 | }
69 |
70 | @Override
71 | public void reset() {}
72 |
73 | @Override
74 | public void resetBuffer() {
75 |
76 | }
77 |
78 | @Override
79 | public void setBufferSize(int arg0) {
80 |
81 | }
82 |
83 | @Override
84 | public void setCharacterEncoding(String arg0) {
85 |
86 | }
87 |
88 | @Override
89 | public void setContentLength(int arg0) {
90 |
91 | }
92 |
93 | @Override
94 | public void setContentLengthLong(long arg0) {
95 |
96 | }
97 |
98 | @Override
99 | public void setContentType(String arg0) {
100 |
101 | }
102 |
103 | @Override
104 | public void setLocale(Locale arg0) {}
105 |
106 | @Override
107 | public void addCookie(Cookie arg0) {}
108 |
109 | @Override
110 | public void addDateHeader(String arg0, long arg1) {}
111 |
112 | @Override
113 | public void addHeader(String arg0, String arg1) {}
114 |
115 | @Override
116 | public void addIntHeader(String arg0, int arg1) {}
117 |
118 | @Override
119 | public boolean containsHeader(String arg0) {
120 | return false;
121 | }
122 |
123 | @Override
124 | public String encodeRedirectURL(String arg0) {
125 | return null;
126 | }
127 |
128 | @Override
129 | public String encodeRedirectUrl(String arg0) {
130 | return null;
131 | }
132 |
133 | @Override
134 | public String encodeURL(String arg0) {
135 | return null;
136 | }
137 |
138 | @Override
139 | public String encodeUrl(String arg0) {
140 | return null;
141 | }
142 |
143 | @Override
144 | public String getHeader(String arg0) {
145 | return null;
146 | }
147 |
148 | @Override
149 | public Collection getHeaderNames() {
150 | return null;
151 | }
152 |
153 | @Override
154 | public Collection getHeaders(String arg0) {
155 | return null;
156 | }
157 |
158 | @Override
159 | public int getStatus() {
160 | return 0;
161 | }
162 |
163 | @Override
164 | public void sendError(int arg0) throws IOException {
165 |
166 | }
167 |
168 | @Override
169 | public void sendError(int arg0, String arg1) throws IOException {
170 |
171 | }
172 |
173 | @Override
174 | public void sendRedirect(String arg0) throws IOException {
175 |
176 | }
177 |
178 | @Override
179 | public void setDateHeader(String arg0, long arg1) {
180 |
181 | }
182 |
183 | @Override
184 | public void setHeader(String arg0, String arg1) {
185 |
186 | }
187 |
188 | @Override
189 | public void setIntHeader(String arg0, int arg1) {
190 |
191 | }
192 |
193 | @Override
194 | public void setStatus(int arg0) {
195 |
196 | }
197 |
198 | @Override
199 | public void setStatus(int arg0, String arg1) {
200 |
201 | }
202 |
203 | }
204 |
--------------------------------------------------------------------------------
/src/test/java/org/edgexfoundry/messaging/ZeroMQEventSubscriberTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.messaging;
20 |
21 | import static org.junit.Assert.assertEquals;
22 |
23 | import org.edgexfoundry.test.category.RequiresNone;
24 | import org.junit.Before;
25 | import org.junit.Test;
26 | import org.junit.experimental.categories.Category;
27 |
28 | @Category({RequiresNone.class})
29 | public class ZeroMQEventSubscriberTest {
30 |
31 | private ZeroMQEventSubscriber subscriber;
32 |
33 | @Before
34 | public void setup() {
35 | subscriber = new ZeroMQEventSubscriber();
36 | }
37 |
38 | @Test
39 | public void testSetters() {
40 | subscriber.setZeromqAddressPort("foobar");
41 | subscriber.setZeromqAddress("foobar");
42 | assertEquals("foobar", subscriber.getZeromqAddress());
43 | assertEquals("foobar", subscriber.getZeromqAddressPort());
44 | }
45 |
46 | // when it cant recieve it will keep trying and eventually overflow
47 | @Test(expected = StackOverflowError.class)
48 | public void testRecieve() {
49 | subscriber.setZeromqAddressPort("foobar");
50 | subscriber.setZeromqAddress("foobar");
51 | subscriber.receive();
52 |
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/test/java/org/edgexfoundry/rule/domain/data/ActionData.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.rule.domain.data;
20 |
21 | import org.edgexfoundry.rule.domain.Action;
22 |
23 | public interface ActionData {
24 |
25 | static final String TEST_BODY = "{\\\"value\\\":\\\"300\\\"}";
26 | static final String TEST_CMD = "12345edf";
27 | static final String TEST_DEVICE = "56789abc";
28 |
29 |
30 | static Action newTestInstance() {
31 | Action action = new Action();
32 | action.setBody(TEST_BODY);
33 | action.setCommand(TEST_CMD);
34 | action.setDevice(TEST_DEVICE);
35 | return action;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/test/java/org/edgexfoundry/rule/domain/data/ConditionData.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.rule.domain.data;
20 |
21 | import java.util.ArrayList;
22 | import java.util.List;
23 |
24 | import org.edgexfoundry.rule.domain.Condition;
25 | import org.edgexfoundry.rule.domain.ValueCheck;
26 |
27 | public interface ConditionData {
28 |
29 | static final String TEST_DEVICE = "56789abc";
30 |
31 | static Condition newTestCondition() {
32 | Condition condition = new Condition();
33 | List checks = new ArrayList<>();
34 | checks.add(ValueCheckData.newTestInstance());
35 | condition.setChecks(checks);
36 | condition.setDevice(TEST_DEVICE);
37 | return condition;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/test/java/org/edgexfoundry/rule/domain/data/RuleData.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.rule.domain.data;
20 |
21 | import org.edgexfoundry.rule.domain.Rule;
22 |
23 | public interface RuleData {
24 |
25 | static final String TEST_RULE1 = "Rule1";
26 | static final String TEST_RULE2 = "Rule2";
27 | static final String TEST_LOG = "slow motor down";
28 |
29 | static Rule newTestInstance() {
30 | Rule rule = new Rule();
31 | rule.setAction(ActionData.newTestInstance());
32 | rule.setCondition(ConditionData.newTestCondition());
33 | rule.setLog(TEST_LOG);
34 | rule.setName(TEST_RULE1);
35 | return rule;
36 | }
37 |
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/test/java/org/edgexfoundry/rule/domain/data/ValueCheckData.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2017 Dell Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | * @microservice: support-rulesengine
15 | * @author: Jim White, Dell
16 | * @version: 1.0.0
17 | *******************************************************************************/
18 |
19 | package org.edgexfoundry.rule.domain.data;
20 |
21 | import org.edgexfoundry.rule.domain.ValueCheck;
22 |
23 | public interface ValueCheckData {
24 |
25 | static final String TEST_PARAM = "rpm";
26 | static final String TEST_OP1 = "Integer.parseInt(value)";
27 | static final String TEST_OP2 = "900";
28 | static final String TEST_OPERATION = ">";
29 |
30 | static ValueCheck newTestInstance() {
31 | ValueCheck check = new ValueCheck();
32 | check.setOperand1(TEST_OP1);
33 | check.setOperand2(TEST_OP2);
34 | check.setOperation(TEST_OPERATION);
35 | check.setParameter(TEST_PARAM);
36 | return check;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/test/resources/bad-rule-template.drl:
--------------------------------------------------------------------------------
1 | package com.foo.bar;
2 | package org.edgexfoundry.rules;
3 | global org.edgexfoundry.engine.CommandExecutor executor;
4 | global org.slf4j.Logger logger;
5 | import org.edgexfoundry.domain.core.Event;
6 | import org.edgexfoundry.domain.core.Reading;
7 | import java.util.Map;
8 | rule "${name}"
9 | when
10 | $e:Event($rlist: readings && device=="${conddevice}")
11 | then
12 | executor.fireCommand("${actiondevice}", "${command}", "${body}");
13 | logger.info("${log}");
14 | end
--------------------------------------------------------------------------------
/src/test/resources/raml/support-rulesengine.raml:
--------------------------------------------------------------------------------
1 | #%RAML 0.8
2 | title: support-rulesengine
3 | version: "1.0.0"
4 | baseUri: "http://localhost:48075/api/v1"
5 | schemas:
6 | -
7 | rule: '{"type":"object","$schema":"http://json-schema.org/draft-03/schema#","description":"EdgeX Support Rules Engine rule","title":"rule","properties":{"name":{"type":"string","required":true,"title":"name"}, "action":{"type":"object","properties":{"device":{"type":"string","required":true,"title":"device"},"command":{"type":"string","required":true,"title":"command"},"body":{"type":"string","required":true,"title":"body"}}}, "condition":{"type":"object","properties":{"device":{"type":"string","required":true,"title":"device"},"checks":{"type":"array","required":false,"title":"checks","items":{"type":"object","properties":{"parameter":{"type":"string","required":false,"title":"parameter"},"operand1":{"type":"string","required":false,"title":"operand1"},"operation":{"type":"string","required":false,"title":"operation"},"operand2":{"type":"string","required":false,"title":"operand2"}}},"uniqueItems":false}}}, "log":{"type":"string","required":false,"title":"log"}}}'
8 | /rule:
9 | displayName: rules
10 | description: example - http://localhost:48075/api/v1/rule
11 | post:
12 | description: Add a new rule. ServcieException (HTTP 503) for unknown or unanticipated issues.
13 | displayName: add a rule
14 | body:
15 | application/json:
16 | schema: rule
17 | example: '{"name":"motortoofastsignal", "condition": {"device":"562114e9e4b0385849b96cd8","checks":[ {"parameter":"RPM", "operand1":"Integer.parseInt(value)", "operation":">","operand2":"1200" } ] }, "action" : {"device":"56325f7ee4b05eaae5a89ce1","command":"56325f6de4b05eaae5a89cdc","body":"{\\\"value\\\":\\\"3\\\"}"},"log":"Patlite warning triggered for engine speed too high" }'
18 | responses:
19 | "200":
20 | description: boolean indicating success of adding the new rule
21 | "503":
22 | description: for unknown or unanticipated issues
23 | get:
24 | description: Return all rule names. ServcieException (HTTP 503) for unknown or unanticipated issues.
25 | displayName: get all rule names
26 | responses:
27 | "200":
28 | description: list of strings
29 | body:
30 | application/json:
31 | example: '["motortoofastsignal"]'
32 | "503":
33 | description: for unknown or unanticipated issues.
34 | /rule/name/{rulename}:
35 | displayName: rule (by name)
36 | description: example - http://localhost:48075/api/v1/rule/name/temptoohi (where temptoohi is the name of a rule)
37 | uriParameters:
38 | rulename:
39 | displayName: rulename
40 | description: Unique name of the rule
41 | type: string
42 | required: true
43 | repeat: false
44 | delete:
45 | description: Remove the rule designated by name. ServcieException (HTTP 503) for unknown or unanticipated issues.
46 | displayName: remove a rule by name
47 | responses:
48 | "200":
49 | description: boolean indicating success of the remove operation
50 | "503":
51 | description: for unknown or unanticipated issues.
52 | /ping:
53 | displayName: Ping Resource
54 | description: example - http://localhost:48075/api/v1/ping
55 | get:
56 | description: Test service providing an indication that the service is available.
57 | displayName: service up check
58 | responses:
59 | "200":
60 | description: return value of "pong"
61 | "503":
62 | description: for unknown or unanticipated issues
63 |
--------------------------------------------------------------------------------
/src/test/resources/rule-template.drl:
--------------------------------------------------------------------------------
1 | package org.edgexfoundry.rules;
2 | global org.edgexfoundry.engine.CommandExecutor executor;
3 | global org.slf4j.Logger logger;
4 | import org.edgexfoundry.domain.core.Event;
5 | import org.edgexfoundry.domain.core.Reading;
6 | import java.util.Map;
7 | rule "${rulename}"
8 | when
9 | $e:Event($rlist: readings && device=="${conddeviceid}")
10 | <#if valuechecks??>
11 | <#assign idx = 0>
12 | <#list valuechecks as valuecheck>
13 | $r${idx}:Reading(name=="${valuecheck.parameter}" && ${valuecheck.operand1} ${valuecheck.operation} ${valuecheck.operand2}) from $rlist
14 | <#assign idx = idx + 1>
15 | #list>
16 | #if>
17 | then
18 | executor.fireCommand("${actiondeviceid}", "${actioncommandid}", "${commandbody}");
19 | logger.info("${log}");
20 | end
--------------------------------------------------------------------------------
/src/test/resources/rule.txt:
--------------------------------------------------------------------------------
1 | package org.edgexfoundry.rules;
2 | global org.edgexfoundry.engine.CommandExecutor executor;
3 | global org.slf4j.Logger logger;
4 | import org.edgexfoundry.domain.core.Event;
5 | import org.edgexfoundry.domain.core.Reading;
6 | import java.util.Map;
7 | rule "Rule1"
8 | when
9 | $e:Event($rlist: readings && device=="56789abc")
10 | $r0:Reading(name=="rpm" && Integer.parseInt(value) > 900) from $rlist
11 | then
12 | executor.fireCommand("56789abc", "12345edf", "{\"value\":\"300\"}");
13 | logger.info("slow motor down");
14 | end
--------------------------------------------------------------------------------