Remove decision parameter from OPADecisionResponse 46/140046/9
authorsrinivasyanamadala <srinivas.yanamadala@techmahindra.com>
Mon, 3 Feb 2025 15:44:33 +0000 (16:44 +0100)
committersrinivasyanamadala <srinivas.yanamadala@techmahindra.com>
Fri, 7 Feb 2025 12:00:34 +0000 (13:00 +0100)
Issue-ID: POLICY-5261
Change-Id: I6e55a4050025fe8626a0a8cd3e114e7d3f137767
Signed-off-by: srinivasyanamadala <srinivas.yanamadala@techmahindra.com>
15 files changed:
api/openapi.yaml
cmd/opa-pdp/opa-pdp.go
go.mod
go.sum
pkg/decision/decision-provider.go
pkg/decision/decision-provider_test.go
pkg/kafkacomm/publisher/pdp-heartbeat.go
pkg/metrics/counters.go
pkg/metrics/counters_test.go
pkg/metrics/statistics-provider.go
pkg/metrics/statistics-provider_test.go
pkg/model/oapicodegen/models.go
test/README.md
version
version.properties

index bd94ec2..8fe3d2c 100644 (file)
-#\r
-#  ========================LICENSE_START=================================\r
-#   Copyright (C) 2024: Deutsche Telekom\r
-#\r
-#   Licensed under the Apache License, Version 2.0 (the "License");\r
-#   you may not use this file except in compliance with the License.\r
-#   You may obtain a copy of the License at\r
-#\r
-#        http://www.apache.org/licenses/LICENSE-2.0\r
-#\r
-#   Unless required by applicable law or agreed to in writing, software\r
-#   distributed under the License is distributed on an "AS IS" BASIS,\r
-#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-#   See the License for the specific language governing permissions and\r
-#  limitations under the License.\r
-#  SPDX-License-Identifier: Apache-2.0\r
-#  ========================LICENSE_END===================================\r
-#\r
-openapi: 3.0.3\r
-info:\r
-  title: "Policy OPA PDP Documentation"\r
-  description: Policy OPA PDP Service\r
-  version: 1.0.2\r
-  x-component: Policy Framework\r
-  x-planned-retirement-date: tbd\r
-  contact:\r
-      name: Deena Mukundan\r
-      email: dm00536893@techmahindra.com\r
-servers:\r
-- url: http://policy-opa-pdp:8282/policy/pdpo/v1\r
-- url: https://policy-opa-pdp:8282/policy/pdpo/v1\r
-tags:\r
-- name: Decision\r
-- name: Statistics\r
-- name: HealthCheck\r
-paths:\r
-  /decision:\r
-    post:\r
-      tags:\r
-      - Decision\r
-      summary: Fetch the decision using specified decision parameters\r
-      description: Returns the policy decision from Policy OPA PDP\r
-      operationId: decision\r
-      parameters:\r
-      - name: X-ONAP-RequestID\r
-        in: header\r
-        description: RequestID for http transaction\r
-        schema:\r
-          type: string\r
-          format: uuid\r
-      requestBody:\r
-        content:\r
-          application/json:\r
-            schema:\r
-              $ref: '#/components/schemas/OPADecisionRequest'\r
-          application/yaml:\r
-            schema:\r
-              $ref: '#/components/schemas/OPADecisionRequest'\r
-        required: false\r
-      responses:\r
-        200:\r
-          description: successful operation\r
-          headers:\r
-            X-LatestVersion:\r
-              description: Used only to communicate an API's latest version\r
-              schema:\r
-                type: string\r
-            X-PatchVersion:\r
-              description: Used only to communicate a PATCH version in a response\r
-                for troubleshooting purposes only, and will not be provided by the\r
-                client on request\r
-              schema:\r
-                type: string\r
-            X-MinorVersion:\r
-              description: Used to request or communicate a MINOR version back from\r
-                the client to the server, and from the server back to the client\r
-              schema:\r
-                type: string\r
-            X-ONAP-RequestID:\r
-              description: Used to track REST transactions for logging purpose\r
-              schema:\r
-                type: string\r
-                format: uuid\r
-          content:\r
-            application/json:\r
-              schema:\r
-                $ref: '#/components/schemas/OPADecisionResponse'\r
-            application/yaml:\r
-              schema:\r
-                $ref: '#/components/schemas/OPADecisionResponse'\r
-        400:\r
-          description: Bad Request\r
-          content:\r
-            application/json:\r
-              schema:\r
-                $ref: '#/components/schemas/ErrorResponse'\r
-            application/yaml:\r
-              schema:\r
-                $ref: '#/components/schemas/ErrorResponse'\r
-        401:\r
-          description: Authentication Error\r
-          content: {}\r
-        403:\r
-          description: Authorization Error\r
-          content: {}\r
-        500:\r
-          description: Internal Server Error\r
-          content: {}\r
-      security:\r
-      - basicAuth: []\r
-      x-interface info:\r
-        last-mod-release: Paris\r
-        pdpo-version: 1.0.0\r
-      x-codegen-request-body-name: body\r
-  /healthcheck:\r
-    get:\r
-      tags:\r
-      - HealthCheck\r
-      summary: Perform a system healthcheck\r
-      description: Provides healthy status of the Policy OPA PDP component\r
-      operationId: healthcheck\r
-      parameters:\r
-      - name: X-ONAP-RequestID\r
-        in: header\r
-        description: RequestID for http transaction\r
-        schema:\r
-          type: string\r
-          format: uuid\r
-      responses:\r
-        200:\r
-          description: successful operation\r
-          headers:\r
-            X-LatestVersion:\r
-              description: Used only to communicate an API's latest version\r
-              schema:\r
-                type: string\r
-            X-PatchVersion:\r
-              description: Used only to communicate a PATCH version in a response\r
-                for troubleshooting purposes only, and will not be provided by the\r
-                client on request\r
-              schema:\r
-                type: string\r
-            X-MinorVersion:\r
-              description: Used to request or communicate a MINOR version back from\r
-                the client to the server, and from the server back to the client\r
-              schema:\r
-                type: string\r
-            X-ONAP-RequestID:\r
-              description: Used to track REST transactions for logging purpose\r
-              schema:\r
-                type: string\r
-                format: uuid\r
-          content:\r
-            application/json:\r
-              schema:\r
-                $ref: '#/components/schemas/HealthCheckReport'\r
-            application/yaml:\r
-              schema:\r
-                $ref: '#/components/schemas/HealthCheckReport'\r
-        401:\r
-          description: Authentication Error\r
-          content: {}\r
-        403:\r
-          description: Authorization Error\r
-          content: {}\r
-        500:\r
-          description: Internal Server Error\r
-          content: {}\r
-      security:\r
-      - basicAuth: []\r
-      x-interface info:\r
-        last-mod-release: Paris\r
-        pdpo-version: 1.0.0\r
-  /statistics:\r
-    get:\r
-      tags:\r
-      - Statistics\r
-      summary: Fetch current statistics\r
-      description: Provides current statistics of the Policy OPA PDP component \r
-      operationId: statistics\r
-      parameters:\r
-      - name: X-ONAP-RequestID\r
-        in: header\r
-        description: RequestID for http transaction\r
-        schema:\r
-          type: string\r
-          format: uuid\r
-      responses:\r
-        200:\r
-          description: successful operation\r
-          headers:\r
-            X-LatestVersion:\r
-              description: Used only to communicate an API's latest version\r
-              schema:\r
-                type: string\r
-            X-PatchVersion:\r
-              description: Used only to communicate a PATCH version in a response\r
-                for troubleshooting purposes only, and will not be provided by the\r
-                client on request\r
-              schema:\r
-                type: string\r
-            X-MinorVersion:\r
-              description: Used to request or communicate a MINOR version back from\r
-                the client to the server, and from the server back to the client\r
-              schema:\r
-                type: string\r
-            X-ONAP-RequestID:\r
-              description: Used to track REST transactions for logging purpose\r
-              schema:\r
-                type: string\r
-                format: uuid\r
-          content:\r
-            application/json:\r
-              schema:\r
-                $ref: '#/components/schemas/StatisticsReport'\r
-            application/yaml:\r
-              schema:\r
-                $ref: '#/components/schemas/StatisticsReport'\r
-        401:\r
-          description: Authentication Error\r
-          content: {}\r
-        403:\r
-          description: Authorization Error\r
-          content: {}\r
-        500:\r
-          description: Internal Server Error\r
-          content: {}\r
-      security:\r
-      - basicAuth: []\r
-      x-interface info:\r
-        last-mod-release: Paris\r
-        pdpo-version: 1.0.0\r
-components:\r
-  schemas:\r
-    ErrorResponse:\r
-      type: object\r
-      properties:\r
-        responseCode:\r
-          type: string\r
-          enum:\r
-          - BAD_REQUEST\r
-          - UNAUTHORIZED\r
-          - METHOD_NOT_ALLOWED\r
-          - NOT_ACCEPTABLE\r
-          - REQUEST_TIMEOUT\r
-          - CONFLICT\r
-          - GONE\r
-          - LENGTH_REQUIRED\r
-          - PRECONDITION_FAILED\r
-          - REQUEST_ENTITY_TOO_LARGE\r
-          - REQUEST_URI_TOO_LONG\r
-          - UNSUPPORTED_MEDIA_TYPE\r
-          - REQUESTED_RANGE_NOT_SATISFIABLE\r
-          - EXPECTATION_FAILED\r
-          - PRECONDITION_REQUIRED\r
-          - TOO_MANY_REQUESTS\r
-          - REQUEST_HEADER_FIELDS_TOO_LARGE\r
-          - INTERNAL_SERVER_ERROR\r
-          - NOT_IMPLEMENTED\r
-          - BAD_GATEWAY\r
-          - SERVICE_UNAVAILABLE\r
-          - GATEWAY_TIMEOUT\r
-          - HTTP_VERSION_NOT_SUPPORTED\r
-          - NETWORK_AUTHENTICATION_REQUIRED\r
-        errorMessage:\r
-          type: string\r
-        policyName:\r
-          type: string\r
-        errorDetails:\r
-          type: array\r
-          items:\r
-            type: string\r
-    OPADecisionRequest:\r
-      type: object\r
-      properties:\r
-        onapName:\r
-          type: string\r
-        onapComponent:\r
-          type: string\r
-        onapInstance:\r
-          type: string\r
-        currentDateTime:\r
-          type: string\r
-          format: date-time\r
-        currentDate:\r
-          type: string\r
-          format: date\r
-        currentTime:\r
-          type: string\r
-          format: date-time\r
-        timeZone:\r
-          type: string\r
-          description: "Timezone in IANA format (e.g., 'America/NewYork', 'Europe/Paris', 'UTC')"\r
-        timeOffset:\r
-          type: string\r
-          pattern: '^[+-]?\d{2}:\d{2}$'\r
-          description: "Time offset in hours and minutes, e.g., '+02:00' or '-05:00'"\r
-        policyName:\r
-          type: string\r
-        policyFilter:\r
-          type: array\r
-          items:\r
-            type: string\r
-        input:\r
-          type: object\r
-          additionalProperties: true\r
-          example:\r
-                    user: alice\r
-                    action: read\r
-                    object: id123\r
-                    type: dog\r
-    HealthCheckReport:\r
-      type: object\r
-      properties:\r
-        name:\r
-          type: string\r
-        url:\r
-          type: string\r
-        healthy:\r
-          type: boolean\r
-        code:\r
-          type: integer\r
-          format: int32\r
-        message:\r
-          type: string\r
-    OPADecisionResponse:\r
-      type: object\r
-      properties:\r
-        statusMessage:\r
-          type: string\r
-        decision:\r
-          type: string\r
-          enum:\r
-          - PERMIT\r
-          - DENY\r
-          - INDETERMINATE\r
-          - NOTAPPLICABLE\r
-        policyName:\r
-          type: string\r
-        output:\r
-          type: object\r
-          additionalProperties: true\r
-    StatisticsReport:\r
-      type: object\r
-      properties:\r
-        code:\r
-          type: integer\r
-          format: int32\r
-        totalPolicyTypesCount:\r
-          type: integer\r
-          format: int64\r
-        totalPoliciesCount:\r
-          type: integer\r
-          format: int64\r
-        totalErrorCount:\r
-          type: integer\r
-          format: int64\r
-        permitDecisionsCount:\r
-          type: integer\r
-          format: int64\r
-        denyDecisionsCount:\r
-          type: integer\r
-          format: int64\r
-        deploySuccessCount:\r
-          type: integer\r
-          format: int64\r
-        deployFailureCount:\r
-          type: integer\r
-          format: int64\r
-        undeploySuccessCount:\r
-          type: integer\r
-          format: int64\r
-        undeployFailureCount:\r
-          type: integer\r
-          format: int64\r
-        indeterminantDecisionsCount:\r
-          type: integer\r
-          format: int64\r
-        querySuccessCount:\r
-          type: integer\r
-          format: int64\r
-        queryFailureCount:\r
-          type: integer\r
-          format: int64\r
-  securitySchemes:\r
-    basicAuth:\r
-      type: http\r
-      description: ""\r
-      scheme: basic\r
+#
+#  ========================LICENSE_START=================================
+#   Copyright (C) 2024-2025: Deutsche Telekom
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#  limitations under the License.
+#  SPDX-License-Identifier: Apache-2.0
+#  ========================LICENSE_END===================================
+#
+openapi: 3.0.3
+info:
+  title: "Policy OPA PDP Documentation"
+  description: Policy OPA PDP Service
+  version: 1.0.2
+  x-component: Policy Framework
+  x-planned-retirement-date: tbd
+  contact:
+      name: Deena Mukundan
+      email: dm00536893@techmahindra.com
+servers:
+- url: http://policy-opa-pdp:8282/policy/pdpo/v1
+- url: https://policy-opa-pdp:8282/policy/pdpo/v1
+tags:
+- name: Decision
+- name: Statistics
+- name: HealthCheck
+
+paths:
+  /decision:
+    post:
+      tags:
+      - Decision
+      summary: Fetch the decision using specified decision parameters
+      description: Returns the policy decision from Policy OPA PDP
+      operationId: decision
+      parameters:
+      - name: X-ONAP-RequestID
+        in: header
+        description: RequestID for http transaction
+        schema:
+          type: string
+          format: uuid
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/OPADecisionRequest'
+          application/yaml:
+            schema:
+              $ref: '#/components/schemas/OPADecisionRequest'
+        required: true
+      responses:
+        200:
+          description: successful operation
+          headers:
+            X-LatestVersion:
+              description: Used only to communicate an API's latest version
+              schema:
+                type: string
+            X-PatchVersion:
+              description: Used only to communicate a PATCH version in a response
+                for troubleshooting purposes only, and will not be provided by the
+                client on request
+              schema:
+                type: string
+            X-MinorVersion:
+              description: Used to request or communicate a MINOR version back from
+                the client to the server, and from the server back to the client
+              schema:
+                type: string
+            X-ONAP-RequestID:
+              description: Used to track REST transactions for logging purpose
+              schema:
+                type: string
+                format: uuid
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/OPADecisionResponse'
+            application/yaml:
+              schema:
+                $ref: '#/components/schemas/OPADecisionResponse'
+            
+        400:
+          description: Bad Request
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+            application/yaml:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+        401:
+          description: Authentication Error
+          content: {}
+        403:
+          description: Authorization Error
+          content: {}
+        500:
+          description: Internal Server Error
+          content: {}
+      security:
+      - basicAuth: []
+      x-interface info:
+        last-mod-release: Paris
+        pdpo-version: 1.0.0
+      x-codegen-request-body-name: body
+  /healthcheck:
+    get:
+      tags:
+      - HealthCheck
+      summary: Perform a system healthcheck
+      description: Provides healthy status of the Policy OPA PDP component
+      operationId: healthcheck
+      parameters:
+      - name: X-ONAP-RequestID
+        in: header
+        description: RequestID for http transaction
+        schema:
+          type: string
+          format: uuid
+      responses:
+        200:
+          description: successful operation
+          headers:
+            X-LatestVersion:
+              description: Used only to communicate an API's latest version
+              schema:
+                type: string
+            X-PatchVersion:
+              description: Used only to communicate a PATCH version in a response
+                for troubleshooting purposes only, and will not be provided by the
+                client on request
+              schema:
+                type: string
+            X-MinorVersion:
+              description: Used to request or communicate a MINOR version back from
+                the client to the server, and from the server back to the client
+              schema:
+                type: string
+            X-ONAP-RequestID:
+              description: Used to track REST transactions for logging purpose
+              schema:
+                type: string
+                format: uuid
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/HealthCheckReport'
+            application/yaml:
+              schema:
+                $ref: '#/components/schemas/HealthCheckReport'
+        401:
+          description: Authentication Error
+          content: {}
+        403:
+          description: Authorization Error
+          content: {}
+        500:
+          description: Internal Server Error
+          content: {}
+      security:
+      - basicAuth: []
+      x-interface info:
+        last-mod-release: Paris
+        pdpo-version: 1.0.0
+  /statistics:
+    get:
+      tags:
+      - Statistics
+      summary: Fetch current statistics
+      description: Provides current statistics of the Policy OPA PDP component 
+      operationId: statistics
+      parameters:
+      - name: X-ONAP-RequestID
+        in: header
+        description: RequestID for http transaction
+        schema:
+          type: string
+          format: uuid
+      responses:
+        200:
+          description: successful operation
+          headers:
+            X-LatestVersion:
+              description: Used only to communicate an API's latest version
+              schema:
+                type: string
+            X-PatchVersion:
+              description: Used only to communicate a PATCH version in a response
+                for troubleshooting purposes only, and will not be provided by the
+                client on request
+              schema:
+                type: string
+            X-MinorVersion:
+              description: Used to request or communicate a MINOR version back from
+                the client to the server, and from the server back to the client
+              schema:
+                type: string
+            X-ONAP-RequestID:
+              description: Used to track REST transactions for logging purpose
+              schema:
+                type: string
+                format: uuid
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/StatisticsReport'
+            application/yaml:
+              schema:
+                $ref: '#/components/schemas/StatisticsReport'
+        401:
+          description: Authentication Error
+          content: {}
+        403:
+          description: Authorization Error
+          content: {}
+        500:
+          description: Internal Server Error
+          content: {}
+      security:
+      - basicAuth: []
+      x-interface info:
+        last-mod-release: Paris
+        pdpo-version: 1.0.0
+components:
+  schemas:
+    ErrorResponse:
+      type: object
+      properties:
+        responseCode:
+          type: string
+          enum:
+          - internal_error
+          - bad_request
+          - evaluation_error
+          - unauthorized
+          - invalid_parameter
+          - invalid_operation
+          - resource_not_found
+          - resource_conflict
+          - undefined_document
+          - opa_undefined_error
+        errorMessage:
+          type: string
+        policyName:
+          type: string
+    OPADecisionRequest:
+      type: object
+      properties:
+        onapName:
+          type: string
+        onapComponent:
+          type: string
+        onapInstance:
+          type: string
+        currentDateTime:
+          type: string
+          format: date-time
+        currentDate:
+          type: string
+          format: date
+        currentTime:
+          type: string
+          format: time
+        timeZone:
+          type: string
+          description: "Timezone in IANA format (e.g., 'America/NewYork', 'Europe/Paris', 'UTC')"
+        timeOffset:
+          type: string
+          pattern: '^[+-]?\d{2}:\d{2}$'
+          description: "Time offset in hours and minutes, e.g., '+02:00' or '-05:00'"
+        policyName:
+          type: string
+        policyFilter:
+          type: array
+          items:
+            type: string
+        input:
+          type: object
+          additionalProperties: true
+          example:
+                    user: alice
+                    action: read
+                    object: id123
+                    type: dog
+      required:
+      - policyName
+      - policyFilter
+      - input
+      
+    HealthCheckReport:
+      type: object
+      properties:
+        name:
+          type: string
+        url:
+          type: string
+        healthy:
+          type: boolean
+        code:
+          type: integer
+          format: int32
+        message:
+          type: string
+    OPADecisionResponse:
+      type: object
+      properties:
+        policyName:
+          type: string
+        statusMessage:
+          type: string
+        output:
+          type: object
+          additionalProperties: true
+      required:
+      - policyName
+      - output
+      
+    StatisticsReport:
+      type: object
+      properties:
+        code:
+          type: integer
+          format: int32
+        totalPolicyTypesCount:
+          type: integer
+          format: int64
+        totalPoliciesCount:
+          type: integer
+          format: int64
+        totalErrorCount:
+          type: integer
+          format: int64
+        deploySuccessCount:
+          type: integer
+          format: int64
+        deployFailureCount:
+          type: integer
+          format: int64
+        undeploySuccessCount:
+          type: integer
+          format: int64
+        undeployFailureCount:
+          type: integer
+          format: int64
+        decisionSuccessCount:
+          type: integer
+          format: int64
+        decisionFailureCount:
+          type: integer
+          format: int64
+    
+  securitySchemes:
+    basicAuth:
+      type: http
+      description: ""
+      scheme: basic
+
index b48bd27..a2cbde2 100644 (file)
@@ -95,15 +95,19 @@ func main() {
        defer producer.Close()
 
        sender := &publisher.RealPdpStatusSender{Producer: producer}
+       // start pdp message handler in a seperate routine
+       handleMessagesFunc(ctx, kc, sender)
+       
+       time.Sleep(10 * time.Second)
+       
        // pdp registration
        isRegistered := registerPDPFunc(sender)
        if !isRegistered {
                return
        }
 
-       // start pdp message handler in a seperate routine
-       handleMessagesFunc(ctx, kc, sender)
-
+       time.Sleep(10 * time.Second)
+       log.Debugf("After registration successful delay")
        // Handle OS Interrupts and Graceful Shutdown
        interruptChannel := make(chan os.Signal, 1)
        signal.Notify(interruptChannel, os.Interrupt, syscall.SIGTERM, syscall.SIGINT, syscall.SIGHUP)
diff --git a/go.mod b/go.mod
index 7130b4d..55d0e3e 100644 (file)
--- a/go.mod
+++ b/go.mod
@@ -1,10 +1,11 @@
 module policy-opa-pdp
 
-go 1.23.4
+go 1.23.3
 
 require (
+       bou.ke/monkey v1.0.2
        github.com/confluentinc/confluent-kafka-go v1.9.2
-       github.com/go-playground/validator/v10 v10.23.0
+       github.com/go-playground/validator/v10 v10.24.0
        github.com/google/uuid v1.6.0
        github.com/oapi-codegen/runtime v1.1.1
        github.com/open-policy-agent/opa v0.70.0
@@ -14,10 +15,10 @@ require (
 )
 
 require (
-       bou.ke/monkey v1.0.2 // indirect
        github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
        github.com/OneOfOne/xxhash v1.2.8 // indirect
        github.com/agnivade/levenshtein v1.2.0 // indirect
+       github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
        github.com/beorn7/perks v1.0.1 // indirect
        github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 // indirect
        github.com/cespare/xxhash/v2 v2.3.0 // indirect
@@ -26,10 +27,9 @@ require (
        github.com/containerd/log v0.1.0 // indirect
        github.com/containerd/platforms v0.2.1 // indirect
        github.com/davecgh/go-spew v1.1.1 // indirect
-       github.com/deepmap/oapi-codegen v1.16.3 // indirect
        github.com/felixge/httpsnoop v1.0.4 // indirect
        github.com/fsnotify/fsnotify v1.7.0 // indirect
-       github.com/gabriel-vasile/mimetype v1.4.3 // indirect
+       github.com/gabriel-vasile/mimetype v1.4.8 // indirect
        github.com/go-ini/ini v1.67.0 // indirect
        github.com/go-logr/logr v1.4.2 // indirect
        github.com/go-logr/stdr v1.2.2 // indirect
@@ -59,11 +59,11 @@ require (
        go.opentelemetry.io/otel/metric v1.28.0 // indirect
        go.opentelemetry.io/otel/sdk v1.28.0 // indirect
        go.opentelemetry.io/otel/trace v1.28.0 // indirect
-       golang.org/x/crypto v0.28.0 // indirect
-       golang.org/x/net v0.30.0 // indirect
-       golang.org/x/sync v0.8.0 // indirect
-       golang.org/x/sys v0.26.0 // indirect
-       golang.org/x/text v0.19.0 // indirect
+       golang.org/x/crypto v0.32.0 // indirect
+       golang.org/x/net v0.34.0 // indirect
+       golang.org/x/sync v0.10.0 // indirect
+       golang.org/x/sys v0.29.0 // indirect
+       golang.org/x/text v0.21.0 // indirect
        golang.org/x/time v0.7.0 // indirect
        google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
        google.golang.org/grpc v1.67.1 // indirect
diff --git a/go.sum b/go.sum
index 4fa9ec5..c376a13 100644 (file)
--- a/go.sum
+++ b/go.sum
@@ -11,16 +11,20 @@ github.com/Microsoft/hcsshim v0.11.7 h1:vl/nj3Bar/CvJSYo7gIQPyRWc9f3c6IeSNavBTSZ
 github.com/Microsoft/hcsshim v0.11.7/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA09d4bExKcU=
 github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
 github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
+github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
 github.com/actgardner/gogen-avro/v10 v10.1.0/go.mod h1:o+ybmVjEa27AAr35FRqU98DJu1fXES56uXniYFv4yDA=
 github.com/actgardner/gogen-avro/v10 v10.2.1/go.mod h1:QUhjeHPchheYmMDni/Nx7VB0RsT/ee8YIgGY/xpEQgQ=
 github.com/actgardner/gogen-avro/v9 v9.1.0/go.mod h1:nyTj6wPqDJoxM3qdnjcLv+EnMDSDFqE0qDpva2QRmKc=
 github.com/agnivade/levenshtein v1.2.0 h1:U9L4IOT0Y3i0TIlUIDJ7rVUziKi/zPbrJGaFrtYH3SY=
 github.com/agnivade/levenshtein v1.2.0/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
+github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
+github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
 github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
 github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
 github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 h1:3uZCA/BLTIu+DqCfguByNMJa2HVHpXvjfy0Dy7g6fuA=
 github.com/bytecodealliance/wasmtime-go/v3 v3.0.2/go.mod h1:RnUjnIXxEJcL6BgCvNyzCCRzZcxCgsZCi+RNlvYor5Q=
 github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
@@ -59,8 +63,6 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/deepmap/oapi-codegen v1.16.3 h1:GT9G86SbQtT1r8ZB+4Cybi9VGdu1P5ieNvNdEoCSbrA=
-github.com/deepmap/oapi-codegen v1.16.3/go.mod h1:JD6ErqeX0nYnhdciLc61Konj3NBASREMlkHOgHn8WAM=
 github.com/dgraph-io/badger/v3 v3.2103.5 h1:ylPa6qzbjYRQMU6jokoj4wzcaweHylt//CH0AKt0akg=
 github.com/dgraph-io/badger/v3 v3.2103.5/go.mod h1:4MPiseMeDQ3FNCYwRbbcBOGJLf5jsE0PPFzRiKjtcdw=
 github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8=
@@ -88,8 +90,8 @@ github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq
 github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og=
 github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
 github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
-github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
-github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
+github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
+github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
 github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
@@ -104,8 +106,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
 github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
 github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
 github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
-github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o=
-github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
+github.com/go-playground/validator/v10 v10.24.0 h1:KHQckvo8G6hlWnrPX4NJJ+aBfWNAE/HH+qdL2cBpCmg=
+github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
 github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
 github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
@@ -171,6 +173,7 @@ github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7
 github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E=
 github.com/jhump/protoreflect v1.12.0/go.mod h1:JytZfP5d0r8pVNLZvai7U/MCuTWITgrI4tTg7puQFKI=
 github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
 github.com/juju/qthttptest v0.1.1/go.mod h1:aTlAv8TYaflIiTDIQYzxnl1QdPjAg8Q8qJMErpKy6A4=
 github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
 github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
@@ -240,6 +243,7 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99
 github.com/santhosh-tekuri/jsonschema/v5 v5.0.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0=
 github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
 github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
 github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
@@ -281,8 +285,8 @@ go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
-golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
+golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
+golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -303,8 +307,8 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
 golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
-golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
+golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
+golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -313,8 +317,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
-golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
+golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -326,15 +330,15 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
-golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
+golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
-golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
 golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
 golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
index 5f45668..a2cedd0 100644 (file)
@@ -1,6 +1,6 @@
 // -
 //   ========================LICENSE_START=================================
-//   Copyright (C) 2024: Deutsche Telekom
+//   Copyright (C) 2024-2025: Deutsche Telekom
 //
 //   Licensed under the Apache License, Version 2.0 (the "License");
 //   you may not use this file except in compliance with the License.
@@ -24,6 +24,9 @@ package decision
 import (
        "context"
        "encoding/json"
+       "github.com/google/uuid"
+       openapi_types "github.com/oapi-codegen/runtime/types"
+       "github.com/open-policy-agent/opa/sdk"
        "net/http"
        "policy-opa-pdp/consts"
        "policy-opa-pdp/pkg/log"
@@ -34,17 +37,13 @@ import (
        "policy-opa-pdp/pkg/pdpstate"
        "policy-opa-pdp/pkg/utils"
        "strings"
-        "fmt"
-       "github.com/google/uuid"
-       openapi_types "github.com/oapi-codegen/runtime/types"
-       "github.com/open-policy-agent/opa/sdk"
 )
 
 // creates a response code map to ErrorResponseResponseCode
 var httpToResponseCode = map[int]oapicodegen.ErrorResponseResponseCode{
-       400: oapicodegen.BADREQUEST,
-       401: oapicodegen.UNAUTHORIZED,
-       500: oapicodegen.INTERNALSERVERERROR,
+       400: oapicodegen.BadRequest,
+       401: oapicodegen.Unauthorized,
+       500: oapicodegen.InternalError,
 }
 
 // Gets responsecode from map
@@ -52,7 +51,7 @@ func GetErrorResponseResponseCode(httpStatus int) oapicodegen.ErrorResponseRespo
        if code, exists := httpToResponseCode[httpStatus]; exists {
                return code
        }
-       return oapicodegen.INTERNALSERVERERROR
+       return oapicodegen.InternalError
 }
 
 // writes a Successful  JSON response to the HTTP response writer
@@ -73,46 +72,92 @@ func writeErrorJSONResponse(res http.ResponseWriter, status int, errorDescriptio
        }
 }
 
+// creates a success decision response
+func createSuccessDecisionResponse(policyName string, output map[string]interface{}) *oapicodegen.OPADecisionResponse {
+       return &oapicodegen.OPADecisionResponse{
+               PolicyName:    policyName,
+               Output:        output,
+       }
+}
+
 // creates a decision response based on the provided parameters
-func createSuccessDecisionResponse(statusMessage, decision, policyName string, output map[string]interface{}) *oapicodegen.OPADecisionResponse {
+func createSuccessDecisionResponseWithStatus(policyName string, output map[string]interface{}, statusMessage string) *oapicodegen.OPADecisionResponse {
        return &oapicodegen.OPADecisionResponse{
-                StatusMessage: &statusMessage,
-               Decision:      (*oapicodegen.OPADecisionResponseDecision)(&decision),
-               PolicyName:    &policyName,
-               Output:        &output,
+               PolicyName:    policyName,
+               Output:        output,
+               StatusMessage: &statusMessage,
        }
 }
 
 // creates a decision response based on the provided parameters
-func createDecisionExceptionResponse(statusCode int, errorMessage string, errorDetails []string, policyName string) *oapicodegen.ErrorResponse {
+func createDecisionExceptionResponse(statusCode int, errorMessage string, policyName string) *oapicodegen.ErrorResponse {
        responseCode := GetErrorResponseResponseCode(statusCode)
        return &oapicodegen.ErrorResponse{
                ResponseCode: (*oapicodegen.ErrorResponseResponseCode)(&responseCode),
                ErrorMessage: &errorMessage,
-               ErrorDetails: &errorDetails,
                PolicyName:   &policyName,
        }
 }
 
-// handles HTTP requests for decisions using OPA.
+// handles HTTP requests for decisions using OPA. 
 func OpaDecision(res http.ResponseWriter, req *http.Request) {
        log.Debugf("PDP received a decision request.")
+       var errorDtls string
+       var httpStatus int
+       var policyId = ""
+
+       requestId, _ := processRequestHeaders(req, res)
+       log.Debugf("Headers processed for requestId: %s", requestId)
+
+       if !isSystemActive() {
+               errorDtls = "System Is In PASSIVE State, error handling request."
+               httpStatus = http.StatusInternalServerError
+       } else if req.Method != http.MethodPost {
+               errorDtls = req.Method + " MethodNotAllowed"
+               httpStatus = http.StatusMethodNotAllowed
+       } else {
+               decisionReq, err := parseRequestBody(req)
+               if err != nil {
+                       errorDtls = err.Error()
+                       httpStatus = http.StatusBadRequest
+               } else if (decisionReq.PolicyName == "") {
+                       errorDtls = "Policy Name is nil which is invalid."
+                       httpStatus = http.StatusBadRequest
+               } else if (decisionReq.PolicyFilter == nil || len(decisionReq.PolicyFilter) == 0)  {
+                       errorDtls = "Policy Filter is nil."
+                       httpStatus = http.StatusBadRequest
+               } else {
+                       opa, err := getOpaInstance()
+                       if err != nil {
+                               errorDtls = "Failed to get OPA instance."
+                               httpStatus = http.StatusInternalServerError
+                               policyId = decisionReq.PolicyName
+                       } else {
+                               processOpaDecision(res, opa, decisionReq)
+                               return
+                       }
+               }
+       }
+       //If it comes here then there will be error
+       sendErrorResponse(errorDtls, res, httpStatus, policyId)
+}
 
+//This function processes the request headers
+func processRequestHeaders(req *http.Request, res http.ResponseWriter) (string, *oapicodegen.DecisionParams) {
        requestId := req.Header.Get("X-ONAP-RequestID")
        var parsedUUID *uuid.UUID
        var decisionParams *oapicodegen.DecisionParams
-       var err error
 
        if requestId != "" && utils.IsValidUUID(requestId) {
                tempUUID, err := uuid.Parse(requestId)
-               if err != nil {
-                       log.Warnf("Error Parsing the requestID: %v", err)
-               } else {
+               if err == nil {
                        parsedUUID = &tempUUID
                        decisionParams = &oapicodegen.DecisionParams{
                                XONAPRequestID: (*openapi_types.UUID)(parsedUUID),
                        }
                        res.Header().Set("X-ONAP-RequestID", decisionParams.XONAPRequestID.String())
+               } else {
+                       log.Warnf("Error Parsing the requestID: %v", err)
                }
        } else {
                requestId = "Unknown"
@@ -123,202 +168,105 @@ func OpaDecision(res http.ResponseWriter, req *http.Request) {
        res.Header().Set("X-PatchVersion", consts.PatchVersion)
        res.Header().Set("X-MinorVersion", consts.MinorVersion)
 
-       log.Debugf("Headers..")
-       for key, value := range res.Header() {
-               log.Debugf("%s: %s", key, value)
-       }
-       // Check if the system is in an active state
-
-       if pdpstate.GetCurrentState() != model.Active {
-               msg := " System Is In PASSIVE State so Unable To Handle Decision wait until it becomes ACTIVE"
-               errorMsg := " System Is In PASSIVE State so error Handling the request"
-               decisionExc := createDecisionExceptionResponse(http.StatusInternalServerError, msg, []string{errorMsg}, "")
-               metrics.IncrementTotalErrorCount()
-               writeErrorJSONResponse(res, http.StatusInternalServerError, msg, *decisionExc)
-               return
-       }
-       ctx := context.Background()
+       return requestId, decisionParams
+}
 
-       // Check if the request method is POST
-       if req.Method != http.MethodPost {
-               msg := " MethodNotAllowed"
-               decisionExc := createDecisionExceptionResponse(http.StatusMethodNotAllowed, "Only POST Method Allowed",
-                       []string{req.Method + msg}, "")
-               metrics.IncrementTotalErrorCount()
-               writeErrorJSONResponse(res, http.StatusMethodNotAllowed, req.Method+msg, *decisionExc)
-               return
-       }
+// This returns whether the system is active or not
+func isSystemActive() bool {
+       return pdpstate.GetCurrentState() == model.Active
+}
 
+//This method parses the body and checks whether it is properly formatted JSON or not
+func parseRequestBody(req *http.Request) (*oapicodegen.OPADecisionRequest, error) {
        var decisionReq oapicodegen.OPADecisionRequest
-
-       // Decode the request body into a DecisionRequest struct
        if err := json.NewDecoder(req.Body).Decode(&decisionReq); err != nil {
-               decisionExc := createDecisionExceptionResponse(http.StatusBadRequest, "Error decoding the request",
-                       []string{err.Error()}, "")
-               metrics.IncrementTotalErrorCount()
-               writeErrorJSONResponse(res, http.StatusBadRequest, err.Error(), *decisionExc)
-               return
+               return nil, err
        }
+       return &decisionReq, nil
+}
 
-       // Check if the policy is provided in the request
-       if decisionReq.PolicyName == nil || *decisionReq.PolicyName == "" {
-               msg := "Policy used to make decision is nil"
-               decisionExc := createDecisionExceptionResponse(http.StatusBadRequest, "policy details not provided",
-                       []string{msg}, "")
-               metrics.IncrementTotalErrorCount()
-               writeErrorJSONResponse(res, http.StatusBadRequest, msg, *decisionExc)
-               return
-       }
+//This function sends the error response
+func sendErrorResponse(msg string, res http.ResponseWriter, httpStatus int, policyName string) {
+       log.Warnf("%s", msg)
+       decisionExc := createDecisionExceptionResponse(httpStatus, msg, policyName)
+       metrics.IncrementTotalErrorCount()
+       writeErrorJSONResponse(res, httpStatus, msg, *decisionExc)
+}
 
-       // Get the OPA singleton instance
-       opa, err := opasdk.GetOPASingletonInstance()
-       if err != nil {
-               msg := "Failed to get OPA instance"
-               log.Warnf("Failed to get OPA instance: %s", err)
-               decisionExc := createDecisionExceptionResponse(http.StatusInternalServerError, "OPA instance creation error", []string{msg},
-                       *decisionReq.PolicyName)
-               metrics.IncrementTotalErrorCount()
-               writeErrorJSONResponse(res, http.StatusInternalServerError, msg, *decisionExc)
-               return
-       }
+//This function returns the opasdk instance
+func getOpaInstance() (*sdk.OPA, error) {
+       return opasdk.GetOPASingletonInstance()
+}
 
+//This function processes the OPA decision
+func processOpaDecision(res http.ResponseWriter, opa *sdk.OPA, decisionReq *oapicodegen.OPADecisionRequest) {
+       ctx := context.Background()
        log.Debugf("SDK making a decision")
-       options := sdk.DecisionOptions{Path: *decisionReq.PolicyName, Input: decisionReq.Input}
-
-       decision, decision_err := opa.Decision(ctx, options)
-
-       jsonOutput, err := json.MarshalIndent(decision, "", "  ")
-       if err != nil {
-               log.Warnf("Error serializing decision output: %v\n", err)
-               return
-       }
-       log.Debugf("RAW opa Decision output:\n%s\n", string(jsonOutput))
-
-       // Check for errors in the OPA decision
-       if decision_err != nil {
-               if strings.Contains(decision_err.Error(), "opa_undefined_error") {
-                       decisionRes := createSuccessDecisionResponse(decision_err.Error(), string(oapicodegen.INDETERMINATE),
-                               *decisionReq.PolicyName, nil)
-                       writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
-                       metrics.IncrementIndeterminantDecisionsCount()
-                       return
-               } else {
-                       decisionExc := createDecisionExceptionResponse(http.StatusBadRequest, "Error from OPA while making decision",
-                               []string{decision_err.Error()}, *decisionReq.PolicyName)
-                       metrics.IncrementTotalErrorCount()
-                       writeErrorJSONResponse(res, http.StatusBadRequest, decision_err.Error(), *decisionExc)
+       var  decisionRes  *oapicodegen.OPADecisionResponse
+       //OPA is seding success with a warning message if "input" parameter is missing, so we need to send success response
+       if (decisionReq.Input == nil) {
+           statusMessage := "{\"warning\":{\"code\":\"api_usage_warning\",\"message\":\"'input' key missing from the request\"}}"
+           decisionRes = createSuccessDecisionResponseWithStatus(decisionReq.PolicyName, nil, statusMessage)
+       } else {
+               options := sdk.DecisionOptions{Path: decisionReq.PolicyName, Input: decisionReq.Input}
+               decisionResult, decisionErr := opa.Decision(ctx, options)
+               jsonOutput, err := json.MarshalIndent(decisionResult, "", "  ")
+               if err != nil {
+                       log.Warnf("Error serializing decision output: %v\n", err)
                        return
                }
-       }
-
-       var policyFilter []string
-       if decisionReq.PolicyFilter != nil {
-               policyFilter = *decisionReq.PolicyFilter
-       }
-
-       // Decision Result Processing
-       outputMap := make(map[string]interface{})
-       // Check if the decision result is a bool or a map
-       switch result := decision.Result.(type) {
-       case bool:
-               // If the result is a boolean (true/false)
-               if result {
-                       // If "allow" is true, process filters if they exist
-                       if len(policyFilter) > 0 {
-                               // If filters are present, we apply them
-                               decisionRes := createSuccessDecisionResponse("OPA Allowed", string(oapicodegen.PERMIT), *decisionReq.PolicyName, nil)
-                               metrics.IncrementPermitDecisionsCount()
-                               writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
-                               return
-                       }
-
-                       // No filters provided, just allow the decision
-                       decisionRes := createSuccessDecisionResponse("OPA Allowed", string(oapicodegen.PERMIT), *decisionReq.PolicyName, nil)
-                       metrics.IncrementPermitDecisionsCount()
-                       writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
+               log.Debugf("RAW opa Decision output:\n%s\n", string(jsonOutput))
+               
+               if decisionErr != nil {
+                       handleOpaDecisionError(res, decisionErr, decisionReq.PolicyName)
                        return
                }
-
-               // If "allow" is false
-               decisionRes := createSuccessDecisionResponse("OPA Denied", string(oapicodegen.DENY), *decisionReq.PolicyName, nil)
-               metrics.IncrementDenyDecisionsCount()
-               writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
-               return
-
-       case map[string]interface{}:
-               if len(policyFilter) > 0 {
-                       // Apply the policy filter if present
-                       filteredResult := applyPolicyFilter(result, policyFilter)
-                       if filteredResultMap, ok := filteredResult.(map[string]interface{}); ok && len(filteredResultMap) > 0 {
-                               outputMap = filteredResultMap
-                       } else {
-                               decisionRes := createSuccessDecisionResponse(
-                                       "No Decision: Result is Empty after applying filter",
-                                       string(oapicodegen.NOTAPPLICABLE),
-                                       *decisionReq.PolicyName, nil)
-                               metrics.IncrementQueryFailureCount()
-                               writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
-                               return
-                       }
-               } else {
-                       // Process result without filters
-                       var statusMessage string
-                       boolValueFound := false
-                       for key, value := range result {
-                               if len(statusMessage) == 0 {
-                                       statusMessage = fmt.Sprintf("%s: %v", key, value)
-                               } else {
-                                       statusMessage = fmt.Sprintf("%s ,%s: %v", statusMessage, key, value)
-                               }
-                               if boolVal, ok := value.(bool); ok {
-                                       boolValueFound = boolVal
-                               }
-                       }
-                       // Return decision based on boolean value
-                       if boolValueFound {
-                               decisionRes := createSuccessDecisionResponse(statusMessage, string(oapicodegen.PERMIT),
-                                       *decisionReq.PolicyName, nil)
-                               metrics.IncrementPermitDecisionsCount()
-                               writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
-                               return
-                       } else {
-                               decisionRes := createSuccessDecisionResponse(statusMessage, string(oapicodegen.DENY),
-                                       *decisionReq.PolicyName, nil)
-                               metrics.IncrementDenyDecisionsCount()
-                               writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
-                               return
-                       }
-
+               
+               var policyFilter []string
+               if decisionReq.PolicyFilter != nil {
+                       policyFilter = decisionReq.PolicyFilter
                }
-
-               // If only non-boolean values were collected
-               if len(outputMap) > 0 {
-                       decisionRes := createSuccessDecisionResponse(
-                               "Decision Not Applicable, Output Only",
-                               string(oapicodegen.NOTAPPLICABLE),
-                               *decisionReq.PolicyName, outputMap)
-                       metrics.IncrementQuerySuccessCount()
-                       writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
+               result, _ := decisionResult.Result.(map[string]interface{})
+               outputMap := processPolicyFilter(result, policyFilter)
+               if outputMap == nil {
+                       decisionRes = createSuccessDecisionResponseWithStatus(decisionReq.PolicyName, outputMap, "Policy Filter is not matching.")
                } else {
-                       decisionRes := createSuccessDecisionResponse(
-                               "No Decision: Result is Empty",
-                               string(oapicodegen.NOTAPPLICABLE),
-                               *decisionReq.PolicyName, nil)
-                       metrics.IncrementQueryFailureCount()
-                       writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
+                       decisionRes = createSuccessDecisionResponse(decisionReq.PolicyName, outputMap)
                }
-               return
+       }
+       metrics.IncrementDecisionSuccessCount()
+       writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
+}
 
-       default:
-               // Handle unexpected types in decision.Result
-               decisionRes := createSuccessDecisionResponse("Invalid decision result format", string(oapicodegen.INDETERMINATE), *decisionReq.PolicyName, nil)
-               metrics.IncrementIndeterminantDecisionsCount()
-               writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
-               return
+//This function validates the errors during decision process
+func handleOpaDecisionError(res http.ResponseWriter, err error, policyName string) {
+       //As per the opa documentation in https://www.openpolicyagent.org/docs/latest/rest-api/#get-a-document-with-input
+       //when the path refers to an undefined document it will return 200 with no result.
+       //opasdk is returning opa_undefined_error for such case, so need to give sucess for such case and
+       //for other cases we have to send error response
+       if strings.Contains(err.Error(), string(oapicodegen.OpaUndefinedError)) {
+               decisionExc := createSuccessDecisionResponse(policyName, nil)
+               metrics.IncrementDecisionSuccessCount()
+               writeOpaJSONResponse(res, http.StatusOK, *decisionExc)
+       } else {
+               decisionExc := createDecisionExceptionResponse(http.StatusInternalServerError, err.Error(), policyName)
+               metrics.IncrementTotalErrorCount()
+               writeErrorJSONResponse(res, http.StatusInternalServerError, err.Error(), *decisionExc)
        }
+}
 
+//This function processes the policy filters
+func processPolicyFilter(result map[string]interface{}, policyFilter []string) map[string]interface{} {
+       if len(policyFilter) > 0 {
+               filteredResult := applyPolicyFilter(result, policyFilter)
+               if filteredMap, ok := filteredResult.(map[string]interface{}); ok && len(filteredMap) > 0 {
+                       return filteredMap
+               }
+       }
+       return nil
 }
 
+
 // Function to apply policy filter to decision result
 func applyPolicyFilter(result map[string]interface{}, filters []string) interface{} {
 
@@ -336,3 +284,4 @@ func applyPolicyFilter(result map[string]interface{}, filters []string) interfac
 
        return filteredOutput
 }
+
index 3a3a105..ef9e36a 100644 (file)
@@ -25,6 +25,7 @@ import (
        "context"
        "encoding/json"
        "errors"
+       "fmt"
        "github.com/open-policy-agent/opa/sdk"
        "net/http"
        "net/http/httptest"
@@ -36,10 +37,10 @@ import (
        "policy-opa-pdp/pkg/pdpstate"
        "reflect"
        "testing"
-
        "github.com/stretchr/testify/assert"
 )
 
+//Test for Invalid request method
 func TestOpaDecision_MethodNotAllowed(t *testing.T) {
        originalGetState := pdpstate.GetCurrentState
        pdpstate.GetCurrentState = func() model.PdpState {
@@ -55,6 +56,7 @@ func TestOpaDecision_MethodNotAllowed(t *testing.T) {
        assert.Contains(t, rec.Body.String(), "MethodNotAllowed")
 }
 
+//Test for invalid JSON request
 func TestOpaDecision_InvalidJSON(t *testing.T) {
        originalGetState := pdpstate.GetCurrentState
        pdpstate.GetCurrentState = func() model.PdpState {
@@ -69,6 +71,7 @@ func TestOpaDecision_InvalidJSON(t *testing.T) {
        assert.Equal(t, http.StatusBadRequest, rec.Code)
 }
 
+//Test for Missing Policy
 func TestOpaDecision_MissingPolicyPath(t *testing.T) {
        originalGetState := pdpstate.GetCurrentState
        pdpstate.GetCurrentState = func() model.PdpState {
@@ -84,9 +87,29 @@ func TestOpaDecision_MissingPolicyPath(t *testing.T) {
        OpaDecision(rec, req)
 
        assert.Equal(t, http.StatusBadRequest, rec.Code)
-       assert.Contains(t, rec.Body.String(), "Policy used to make decision is nil")
+       assert.Contains(t, rec.Body.String(), "Policy Name is nil which is invalid")
+}
+
+//Test for Missing Policy Filter
+func TestOpaDecision_MissingPolicyFilter(t *testing.T) {
+       originalGetState := pdpstate.GetCurrentState
+       pdpstate.GetCurrentState = func() model.PdpState {
+               return model.Active
+       }
+       defer func() { pdpstate.GetCurrentState = originalGetState }()
+       body := map[string]interface{}{"onapName": "CDS", "policyName": "data.policy", "onapComponent": "CDS", "onapInstance": "CDS", "requestId": "8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1", "input": nil}
+
+       jsonBody, _ := json.Marshal(body)
+       req := httptest.NewRequest(http.MethodPost, "/", bytes.NewBuffer(jsonBody))
+       rec := httptest.NewRecorder()
+
+       OpaDecision(rec, req)
+
+       assert.Equal(t, http.StatusBadRequest, rec.Code)
+       assert.Contains(t, rec.Body.String(), "Policy Filter is nil")
 }
 
+//Test for OPA Instance Error
 func TestOpaDecision_GetInstanceError(t *testing.T) {
        originalGetState := pdpstate.GetCurrentState
        pdpstate.GetCurrentState = func() model.PdpState {
@@ -103,6 +126,7 @@ func TestOpaDecision_GetInstanceError(t *testing.T) {
        assert.Equal(t, http.StatusBadRequest, rec.Code)
 }
 
+//Test for OPA decision Error
 func TestOpaDecision_OPADecisionError(t *testing.T) {
        originalGetState := pdpstate.GetCurrentState
        pdpstate.GetCurrentState = func() model.PdpState {
@@ -127,6 +151,7 @@ func TestOpaDecision_OPADecisionError(t *testing.T) {
        assert.Equal(t, http.StatusBadRequest, rec.Code)
 }
 
+//Test for system in passive State
 func TestOpaDecision_PassiveState(t *testing.T) {
        originalGetState := pdpstate.GetCurrentState
        pdpstate.GetCurrentState = func() model.PdpState {
@@ -139,50 +164,45 @@ func TestOpaDecision_PassiveState(t *testing.T) {
        OpaDecision(rec, req)
 
        assert.Equal(t, http.StatusInternalServerError, rec.Code)
-       assert.Contains(t, rec.Body.String(), " System Is In PASSIVE State")
+       assert.Contains(t, rec.Body.String(), "System Is In PASSIVE State")
 }
 
-// New
 // TestOpaDecision_ValidRequest tests if the request is handled correctly
 // Utility function to return a pointer to a string
-func ptrString(s string) *string {
-       return &s
+func ptrString(s string) string {
+       return s
 }
 
+func ptrStringEx(s string) *string {
+       return &s
+}
 // Utility function to return a pointer to a map
-func ptrMap(m map[string]interface{}) *map[string]interface{} {
-       return &m
+func ptrMap(m map[string]interface{}) map[string]interface{} {
+       return m
 }
 
 // Utility function to return a pointer to a OPADecisionResponseDecision
-func ptrOPADecisionResponseDecision(decision oapicodegen.OPADecisionResponseDecision) *oapicodegen.OPADecisionResponseDecision {
-       return &decision
-}
-
 func TestWriteOpaJSONResponse(t *testing.T) {
        rec := httptest.NewRecorder()
 
-       // Use correct type for Decision, which is a pointer to OPADecisionResponseDecision
-       decision := oapicodegen.OPADecisionResponseDecision("PERMIT")
        data := &oapicodegen.OPADecisionResponse{
-               Decision:   ptrOPADecisionResponseDecision(decision), // Correct use of pointer
-               PolicyName: ptrString("test-policy"),
-               Output:     ptrMap(map[string]interface{}{"key": "value"}),
+       PolicyName: ptrString("test-policy"),
+       Output:     ptrMap(map[string]interface{}{"key": "value"}),
        }
 
        writeOpaJSONResponse(rec, http.StatusOK, *data)
 
        assert.Equal(t, http.StatusOK, rec.Code)
-       assert.Contains(t, rec.Body.String(), `"decision":"PERMIT"`)
        assert.Contains(t, rec.Body.String(), `"policyName":"test-policy"`)
 }
 
+//Test for JSON response error
 func TestWriteErrorJSONResponse(t *testing.T) {
        rec := httptest.NewRecorder()
 
        // ErrorResponse struct uses pointers for string fields, so we use ptrString()
        errorResponse := oapicodegen.ErrorResponse{
-               ErrorMessage: ptrString("Bad Request"),
+               ErrorMessage: ptrStringEx("Bad Request"),
        }
 
        writeErrorJSONResponse(rec, http.StatusBadRequest, "Bad Request", errorResponse)
@@ -191,31 +211,26 @@ func TestWriteErrorJSONResponse(t *testing.T) {
        assert.Contains(t, rec.Body.String(), `"errorMessage":"Bad Request"`)
 }
 
+//Test for Success Decision Response
 func TestCreateSuccessDecisionResponse(t *testing.T) {
        // Input values for creating the response
-       statusMessage := "Success"
-       decision := oapicodegen.OPADecisionResponseDecision("PERMIT")
        policyName := "policy-name"
        output := map[string]interface{}{"key": "value"}
 
        // Call the createSuccessDecisionResponse function
-       response := createSuccessDecisionResponse(statusMessage, string(decision), policyName, output)
+       response := createSuccessDecisionResponse(
+       policyName, output)
 
        // Assertions
 
-       // Check the StatusMessage field
-       assert.Equal(t, *response.StatusMessage, statusMessage, "StatusMessage should match")
-
-       // Check the Decision field (it should be a pointer to the string "PERMIT")
-       assert.Equal(t, *response.Decision, decision, "Decision should match")
-
        // Check the PolicyName field
-       assert.Equal(t, *response.PolicyName, policyName, "PolicyName should match")
+       assert.Equal(t, response.PolicyName, policyName, "PolicyName should match")
 
        // Check the Output field
-       assert.Equal(t, *response.Output, output, "Output should match")
+       assert.Equal(t, response.Output, output, "Output should match")
 }
 
+//Test for policy filter
 func TestApplyPolicyFilter(t *testing.T) {
        originalPolicy := map[string]interface{}{
                "policy1": map[string]interface{}{"key1": "value1"},
@@ -229,40 +244,34 @@ func TestApplyPolicyFilter(t *testing.T) {
        assert.Contains(t, result, "policy1")
 }
 
+//Test for Opa response error
 func TestWriteOpaJSONResponse_Error(t *testing.T) {
        rec := httptest.NewRecorder()
 
        // Simulate an error response
-       statusMessage := "Error processing request"
-       decision := oapicodegen.OPADecisionResponseDecision("DENY")
        policyName := "error-policy"
        output := map[string]interface{}{"errorDetail": "Invalid input"}
 
        // Create a response object for error scenario
        data := &oapicodegen.OPADecisionResponse{
-               Decision:      ptrOPADecisionResponseDecision(decision), // Use correct pointer
                PolicyName:    ptrString(policyName),
                Output:        ptrMap(output),
-               StatusMessage: ptrString(statusMessage),
        }
 
        writeOpaJSONResponse(rec, http.StatusBadRequest, *data)
 
        // Assertions
        assert.Equal(t, http.StatusBadRequest, rec.Code, "Expected HTTP 400 status code")
-       assert.Contains(t, rec.Body.String(), `"decision":"DENY"`, "Response should contain 'DENY' decision")
        assert.Contains(t, rec.Body.String(), `"policyName":"error-policy"`, "Response should contain the policy name")
-       assert.Contains(t, rec.Body.String(), `"statusMessage":"Error processing request"`, "Response should contain the status message")
        assert.Contains(t, rec.Body.String(), `"errorDetail":"Invalid input"`, "Response should contain the error detail")
 }
 
+//Test for JSON response success
 func TestWriteOpaJSONResponse_Success(t *testing.T) {
        // Prepare test data
        decisionRes := oapicodegen.OPADecisionResponse{
-               StatusMessage: ptrString("Success"),
-               Decision:      (*oapicodegen.OPADecisionResponseDecision)(ptrString("PERMIT")),
                PolicyName:    ptrString("TestPolicy"),
-               Output:        &map[string]interface{}{"key": "value"},
+               Output:        map[string]interface{}{"key": "value"},
        }
 
        // Create a mock HTTP response writer
@@ -286,16 +295,14 @@ func TestWriteOpaJSONResponse_Success(t *testing.T) {
        if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
                t.Fatalf("Failed to decode response body: %v", err)
        }
-       if *result.StatusMessage != "Success" {
-               t.Errorf("Expected StatusMessage 'Success', got '%s'", *result.StatusMessage)
-       }
 }
 
+// Test for JSON encoding errors
 func TestWriteOpaJSONResponse_EncodingError(t *testing.T) {
-       // Prepare invalid test data to trigger JSON encoding error
-       decisionRes := oapicodegen.OPADecisionResponse{
+               // Prepare invalid test data to trigger JSON encoding error
+               decisionRes := oapicodegen.OPADecisionResponse {
                // Introducing an invalid type to cause encoding failure
-               Output: &map[string]interface{}{"key": make(chan int)},
+               Output: map[string]interface{}{"key": make(chan int)},
        }
 
        // Create a mock HTTP response writer
@@ -319,12 +326,6 @@ func TestWriteOpaJSONResponse_EncodingError(t *testing.T) {
 var GetOPASingletonInstance = opasdk.GetOPASingletonInstance
 
 var mockDecisionResult = &sdk.DecisionResult{
-       Result: map[string]interface{}{
-               "allowed": true,
-       },
-}
-
-var mockDecisionResult2 = &sdk.DecisionResult{
        Result: map[string]interface{}{
                "allow": "true",
        },
@@ -335,9 +336,6 @@ var mockDecisionResultUnexp = &sdk.DecisionResult{
                123: 123,
        },
 }
-var mockDecisionResultBoolFalse = &sdk.DecisionResult{
-       Result: false,
-}
 
 var mockDecisionResultBool = &sdk.DecisionResult{
        Result: true,
@@ -345,14 +343,12 @@ var mockDecisionResultBool = &sdk.DecisionResult{
 
 var mockDecisionReq = oapicodegen.OPADecisionRequest{
        PolicyName:   ptrString("mockPolicy"),
-       PolicyFilter: &[]string{"filter1", "filter2"},
-       //Input:        map[string]interface{}{"key": "value"},
+       PolicyFilter: []string{"filter1", "filter2"},
 }
 
 var mockDecisionReq2 = oapicodegen.OPADecisionRequest{
        PolicyName:   ptrString("mockPolicy"),
-       PolicyFilter: &[]string{"allow", "filter2"},
-       //Input:        map[string]interface{}{"key": "value"},
+       PolicyFilter: []string{"allow", "filter2"},
 }
 
 // Test to check invalid UUID in request
@@ -378,7 +374,10 @@ func Test_Invalid_request_UUID(t *testing.T) {
                return model.Active
        }
        defer func() { pdpstate.GetCurrentState = originalGetState }()
-       body := map[string]interface{}{"PolicyName": "data.policy"}
+       jsonString := `{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"s3","policyFilter":["allow"],"input":{"content" : "content"}}`
+       var decisionReq oapicodegen.OPADecisionRequest
+       json.Unmarshal([]byte(jsonString), &decisionReq)
+       body := map[string]interface{}{"PolicyName": decisionReq.PolicyName, "PolicyFilter": decisionReq.PolicyFilter,}
        jsonBody, _ := json.Marshal(body)
        req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer(jsonBody))
        req.Header.Set("X-ONAP-RequestID", "valid-uuid")
@@ -425,14 +424,15 @@ func Test_valid_HTTP_method(t *testing.T) {
        )
        defer patch.Unpatch()
 
-       body := map[string]interface{}{"PolicyName": jsonString}
+       var decisionReq oapicodegen.OPADecisionRequest
+       json.Unmarshal([]byte(jsonString), &decisionReq)
+       body := map[string]interface{}{"PolicyName": decisionReq.PolicyName, "PolicyFilter": decisionReq.PolicyFilter,}
        jsonBody, _ := json.Marshal(body)
        req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer(jsonBody))
        res := httptest.NewRecorder()
        OpaDecision(res, req)
 
        assert.Equal(t, http.StatusOK, res.Code)
-       assert.Contains(t, res.Body.String(), "PERMIT")
 }
 
 // Test for Marshalling error in Decision Result
@@ -458,115 +458,103 @@ func Test_Error_Marshalling(t *testing.T) {
                },
        )
        defer patch.Unpatch()
-       body := map[string]interface{}{"PolicyName": jsonString}
-       jsonBody, _ := json.Marshal(body)
-       req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer(jsonBody))
-       res := httptest.NewRecorder()
-
-       OpaDecision(res, req)
-       assert.Equal(t, http.StatusOK, res.Code)
-       assert.Empty(t, res.Body.String())
-}
 
-// Test for Policy filter with invalid/not applicable Decision result
-func Test_Policy_Filter_with_invalid_decision_result(t *testing.T) {
-       originalGetState := pdpstate.GetCurrentState
-       pdpstate.GetCurrentState = func() model.PdpState {
-               return model.Active
-       }
-       defer func() { pdpstate.GetCurrentState = originalGetState }()
-       jsonString := `{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"s3","policyFilter":["allow"],"input":{"content" : "content"}}`
-
-       var patch *monkey.PatchGuard
-
-       patch = monkey.PatchInstanceMethod(
-               reflect.TypeOf(&sdk.OPA{}), "Decision",
-               func(_ *sdk.OPA, _ context.Context, _ sdk.DecisionOptions) (*sdk.DecisionResult, error) {
-                       return mockDecisionResult, nil
-               },
-       )
-       defer patch.Unpatch()
-       body := map[string]interface{}{"PolicyName": jsonString}
+       var decisionReq oapicodegen.OPADecisionRequest
+       json.Unmarshal([]byte(jsonString), &decisionReq)
+       body := map[string]interface{}{"PolicyName": decisionReq.PolicyName, "PolicyFilter": decisionReq.PolicyFilter,}
        jsonBody, _ := json.Marshal(body)
        req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer(jsonBody))
        res := httptest.NewRecorder()
 
-       var patch1 *monkey.PatchGuard
-       patch1 = monkey.PatchInstanceMethod(
-               reflect.TypeOf(&json.Decoder{}), "Decode",
-               func(_ *json.Decoder, v interface{}) error {
-                       if req, ok := v.(*oapicodegen.OPADecisionRequest); ok {
-                               *req = mockDecisionReq
-                       }
-                       return nil
-               },
-       )
-       defer patch1.Unpatch()
        OpaDecision(res, req)
-
        assert.Equal(t, http.StatusOK, res.Code)
-       assert.Contains(t, res.Body.String(), "NOTAPPLICABLE")
+       assert.NotEmpty(t, res.Body.String())
 }
 
-// Test with OPA Decision of boolean type true
-func Test_with_boolean_OPA_Decision(t *testing.T) {
+// Test for Invalid Decision error in Decision Result
+func Test_Invalid_Decision(t *testing.T) {
+       // Mock PDP state
        originalGetState := pdpstate.GetCurrentState
        pdpstate.GetCurrentState = func() model.PdpState {
                return model.Active
        }
        defer func() { pdpstate.GetCurrentState = originalGetState }()
-       jsonString := `{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"s3","policyFilter":["allow"],"input":{"content" : "content"}}`
 
-       var patch *monkey.PatchGuard
-       patch = monkey.PatchInstanceMethod(
+       // Define a request body that matches expected input format
+       jsonString := `{
+               "policyName": "s3",
+               "policyFilter": ["allow"],
+               "input": {"content": "content"}
+       }`
+       
+       // Patch the OPA Decision method to return an error
+       patch := monkey.PatchInstanceMethod(
                reflect.TypeOf(&sdk.OPA{}), "Decision",
                func(_ *sdk.OPA, _ context.Context, _ sdk.DecisionOptions) (*sdk.DecisionResult, error) {
-                       return mockDecisionResultBool, nil
+                       // Return an explicit error
+                       return nil, fmt.Errorf("opa_undefined_error")
                },
        )
        defer patch.Unpatch()
 
-       body := map[string]interface{}{"PolicyName": jsonString}
-       jsonBody, _ := json.Marshal(body)
-       req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer(jsonBody))
+       // Create a test HTTP request
+       req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer([]byte(jsonString)))
+       req.Header.Set("Content-Type", "application/json")
        res := httptest.NewRecorder()
+
+       // Call the handler function that processes OPA decision
        OpaDecision(res, req)
 
-       assert.Equal(t, http.StatusOK, res.Code)
-       assert.Contains(t, res.Body.String(), "PERMIT")
+       // Assert that the response status code is 400
+       assert.Equal(t, 200, res.Code)
 }
 
-// Test with OPA Decision of boolean type with false
-func Test_Successful_decision_allow_false(t *testing.T) {
+// Test for Invalid Decision error in Decision Result
+func Test_Valid_Decision_String(t *testing.T) {
+       // Mock PDP state
        originalGetState := pdpstate.GetCurrentState
        pdpstate.GetCurrentState = func() model.PdpState {
                return model.Active
        }
        defer func() { pdpstate.GetCurrentState = originalGetState }()
-       jsonString := `{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"s3","policyFilter":["allow"],"input":{"content" : "content"}}`
 
-       var patch *monkey.PatchGuard
-       patch = monkey.PatchInstanceMethod(
+       // Define a request body that matches expected input format
+       jsonString := `{
+               "policyName": "s3",
+               "policyFilter": ["allow"],
+               "input": {"content": "content"}
+       }`
+       
+       // Patch the OPA Decision method to return an error
+       patch := monkey.PatchInstanceMethod(
                reflect.TypeOf(&sdk.OPA{}), "Decision",
                func(_ *sdk.OPA, _ context.Context, _ sdk.DecisionOptions) (*sdk.DecisionResult, error) {
-                       return mockDecisionResultBool, nil
+                               // Return an explicit error
+                               mockDecisionResult := &sdk.DecisionResult{
+                               Result: map[string]interface{}{
+                                       "allowed": "true",
+                               },
+                       }
+                       return mockDecisionResult, nil
                },
        )
+
        defer patch.Unpatch()
 
-       body := map[string]interface{}{"PolicyName": jsonString}
-       jsonBody, _ := json.Marshal(body)
-       req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer(jsonBody))
+       // Create a test HTTP request
+       req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer([]byte(jsonString)))
+       req.Header.Set("Content-Type", "application/json")
        res := httptest.NewRecorder()
 
+       // Call the handler function that processes OPA decision
        OpaDecision(res, req)
 
-       assert.Equal(t, http.StatusOK, res.Code)
-       assert.Contains(t, res.Body.String(), "OPA Allowed")
+       // Assert that the response status code is 400
+       assert.Equal(t, 200, res.Code)
 }
 
-// Test with OPA Decision of boolean type with false having filter
-func Test_decision_result_false_with_Filter(t *testing.T) {
+// Test for Policy filter with invalid/not applicable Decision result
+func Test_Policy_Filter_with_invalid_decision_result(t *testing.T) {
        originalGetState := pdpstate.GetCurrentState
        pdpstate.GetCurrentState = func() model.PdpState {
                return model.Active
@@ -579,8 +567,7 @@ func Test_decision_result_false_with_Filter(t *testing.T) {
        patch = monkey.PatchInstanceMethod(
                reflect.TypeOf(&sdk.OPA{}), "Decision",
                func(_ *sdk.OPA, _ context.Context, _ sdk.DecisionOptions) (*sdk.DecisionResult, error) {
-                       // Simulate an error to trigger the second error block
-                       return mockDecisionResultBool, nil
+                       return mockDecisionResult, nil
                },
        )
        defer patch.Unpatch()
@@ -603,11 +590,10 @@ func Test_decision_result_false_with_Filter(t *testing.T) {
        OpaDecision(res, req)
 
        assert.Equal(t, http.StatusOK, res.Code)
-       assert.Contains(t, res.Body.String(), "OPA Allowed")
 }
 
-// Test with OPA Decision of boolean type with true having filter
-func Test_decision_result_true_with_Filter(t *testing.T) {
+// Test with OPA Decision of boolean type true
+func Test_with_boolean_OPA_Decision(t *testing.T) {
        originalGetState := pdpstate.GetCurrentState
        pdpstate.GetCurrentState = func() model.PdpState {
                return model.Active
@@ -616,35 +602,26 @@ func Test_decision_result_true_with_Filter(t *testing.T) {
        jsonString := `{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"s3","policyFilter":["allow"],"input":{"content" : "content"}}`
 
        var patch *monkey.PatchGuard
-
        patch = monkey.PatchInstanceMethod(
                reflect.TypeOf(&sdk.OPA{}), "Decision",
                func(_ *sdk.OPA, _ context.Context, _ sdk.DecisionOptions) (*sdk.DecisionResult, error) {
-                       return mockDecisionResultBoolFalse, nil
+                       return mockDecisionResultBool, nil
                },
        )
        defer patch.Unpatch()
-       body := map[string]interface{}{"PolicyName": jsonString}
+
+       var decisionReq oapicodegen.OPADecisionRequest
+        json.Unmarshal([]byte(jsonString), &decisionReq)
+        body := map[string]interface{}{"PolicyName": decisionReq.PolicyName, "PolicyFilter": decisionReq.PolicyFilter,}
        jsonBody, _ := json.Marshal(body)
        req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer(jsonBody))
        res := httptest.NewRecorder()
-       var patch1 *monkey.PatchGuard
-       patch1 = monkey.PatchInstanceMethod(
-               reflect.TypeOf(&json.Decoder{}), "Decode",
-               func(_ *json.Decoder, v interface{}) error {
-                       if req, ok := v.(*oapicodegen.OPADecisionRequest); ok {
-                               *req = mockDecisionReq
-                       }
-                       return nil
-               },
-       )
-       defer patch1.Unpatch()
        OpaDecision(res, req)
 
        assert.Equal(t, http.StatusOK, res.Code)
-       assert.Contains(t, res.Body.String(), "Denied")
 }
 
+
 // Test with OPA Decision with String type
 func Test_decision_Result_String(t *testing.T) {
        originalGetState := pdpstate.GetCurrentState
@@ -652,7 +629,7 @@ func Test_decision_Result_String(t *testing.T) {
                return model.Active
        }
        defer func() { pdpstate.GetCurrentState = originalGetState }()
-       jsonString := `{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"s3","policyFilter":["allow"],"input":{"content" : "content"}}`
+       jsonString := `{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"s3","policyFilter":["allowed"],"input":{"content" : "content"}}`
 
        var patch *monkey.PatchGuard
 
@@ -662,14 +639,16 @@ func Test_decision_Result_String(t *testing.T) {
                        // Create a mock result with an incompatible field (e.g., a channel)
                        mockDecisionResult := &sdk.DecisionResult{
                                Result: map[string]interface{}{
-                                       "allowed": "deny",
+                                       "allowed": "true",
                                },
                        }
                        return mockDecisionResult, nil
                },
        )
        defer patch.Unpatch()
-       body := map[string]interface{}{"PolicyName": jsonString}
+       var decisionReq oapicodegen.OPADecisionRequest
+       json.Unmarshal([]byte(jsonString), &decisionReq)
+       body := map[string]interface{}{"PolicyName": decisionReq.PolicyName, "PolicyFilter": decisionReq.PolicyFilter,}
        jsonBody, _ := json.Marshal(body)
        req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer(jsonBody))
        res := httptest.NewRecorder()
@@ -677,7 +656,6 @@ func Test_decision_Result_String(t *testing.T) {
        OpaDecision(res, req)
 
        assert.Equal(t, http.StatusOK, res.Code)
-       assert.Contains(t, res.Body.String(), "DENY")
 }
 
 // Test with OPA Decision with String type wth filtered result
@@ -695,7 +673,7 @@ func Test_decision_Result_String_with_filtered_Result(t *testing.T) {
                reflect.TypeOf(&sdk.OPA{}), "Decision",
                func(_ *sdk.OPA, _ context.Context, _ sdk.DecisionOptions) (*sdk.DecisionResult, error) {
                        // Simulate an error to trigger the second error block
-                       return mockDecisionResult2, nil
+                       return mockDecisionResult, nil
                },
        )
        defer patch.Unpatch()
@@ -717,7 +695,6 @@ func Test_decision_Result_String_with_filtered_Result(t *testing.T) {
        OpaDecision(res, req)
 
        assert.Equal(t, http.StatusOK, res.Code)
-       assert.Contains(t, res.Body.String(), "NOTAPPLICABLE")
 
 }
 
@@ -758,7 +735,6 @@ func Test_decision_with_filtered_Result_as_unexpected_Res_Type(t *testing.T) {
        OpaDecision(res, req)
 
        assert.Equal(t, http.StatusOK, res.Code)
-       assert.Contains(t, res.Body.String(), "INDETERMINATE")
 }
 
 // Test with OPA Decision with Error in response
@@ -767,9 +743,7 @@ func TestWriteErrorJSONResponse_EncodingFailure(t *testing.T) {
        errorMessage := "Test error message"
        policyName := "TestPolicy"
        responseCode := oapicodegen.ErrorResponseResponseCode("500")
-       errorDetails := []string{"Detail 1", "Detail 2"}
        mockDecisionExc := oapicodegen.ErrorResponse{
-               ErrorDetails: &errorDetails,
                ErrorMessage: &errorMessage,
                PolicyName:   &policyName,
                ResponseCode: &responseCode,
index 0c48189..42a5e70 100644 (file)
@@ -69,7 +69,9 @@ func StartHeartbeatIntervalTimer(intervalMs int64, s PdpStatusSender) {
                for {
                        select {
                        case <-ticker.C:
-                               sendPDPHeartBeat(s)
+                               if err := sendPDPHeartBeat(s); err != nil {
+                                       log.Errorf("Failed to send PDP Heartbeat: %v", err)
+                               }
                        case <-stopChan:
                                ticker.Stop()
                                return
index bbf148b..e126554 100644 (file)
@@ -1,6 +1,6 @@
 // -
 //   ========================LICENSE_START=================================
-//   Copyright (C) 2024: Deutsche Telekom
+//   Copyright (C) 2024-2025: Deutsche Telekom
 //
 //   Licensed under the Apache License, Version 2.0 (the "License");
 //   you may not use this file except in compliance with the License.
@@ -22,55 +22,14 @@ package metrics
 import "sync"
 
 // global counter variables
-var IndeterminantDecisionsCount int64
-var PermitDecisionsCount int64
-var DenyDecisionsCount int64
 var TotalErrorCount int64
-var QuerySuccessCount int64
-var QueryFailureCount int64
+var DecisionSuccessCount int64
+var DecisionFailureCount int64
 var mu sync.Mutex
 
-// Increment counter
-func IncrementIndeterminantDecisionsCount() {
-       mu.Lock()
-       IndeterminantDecisionsCount++
-       mu.Unlock()
-}
-
-// returns pointer to the counter
-func IndeterminantDecisionsCountRef() *int64 {
-       mu.Lock()
-       defer mu.Unlock()
-       return &IndeterminantDecisionsCount
-}
-
-// Increment counter
-func IncrementPermitDecisionsCount() {
-       mu.Lock()
-       PermitDecisionsCount++
-       mu.Unlock()
-}
 
-// returns pointer to the counter
-func PermitDecisionsCountRef() *int64 {
-       mu.Lock()
-       defer mu.Unlock()
-       return &PermitDecisionsCount
-}
 
-// Increment counter
-func IncrementDenyDecisionsCount() {
-       mu.Lock()
-       DenyDecisionsCount++
-       mu.Unlock()
-}
 
-// returns pointer to the counter
-func DenyDecisionsCountRef() *int64 {
-       mu.Lock()
-       defer mu.Unlock()
-       return &DenyDecisionsCount
-}
 
 // Increment counter
 func IncrementTotalErrorCount() {
@@ -87,31 +46,31 @@ func TotalErrorCountRef() *int64 {
 }
 
 // Increment counter
-func IncrementQuerySuccessCount() {
+func IncrementDecisionSuccessCount() {
        mu.Lock()
-       QuerySuccessCount++
+       DecisionSuccessCount++
        mu.Unlock()
 }
 
 // returns pointer to the counter
-func TotalQuerySuccessCountRef() *int64 {
+func TotalDecisionSuccessCountRef() *int64 {
        mu.Lock()
        defer mu.Unlock()
-       return &QuerySuccessCount
+       return &DecisionSuccessCount
 
 }
 
 // Increment counter
-func IncrementQueryFailureCount() {
+func IncrementDecisionFailureCount() {
        mu.Lock()
-       QueryFailureCount++
+       DecisionFailureCount++
        mu.Unlock()
 }
 
 // returns pointer to the counter
-func TotalQueryFailureCountRef() *int64 {
+func TotalDecisionFailureCountRef() *int64 {
        mu.Lock()
        defer mu.Unlock()
-       return &QueryFailureCount
+       return &DecisionFailureCount
 
 }
index e421e46..ba8646b 100644 (file)
@@ -29,42 +29,6 @@ import (
 func TestCounters(t *testing.T) {
        var wg sync.WaitGroup
 
-       // Test IncrementIndeterminantDecisionsCount and IndeterminantDecisionsCountRef
-       IndeterminantDecisionsCount = 0
-       wg.Add(10)
-       for i := 0; i < 10; i++ {
-               go func() {
-                       defer wg.Done()
-                       IncrementIndeterminantDecisionsCount()
-               }()
-       }
-       wg.Wait()
-       assert.Equal(t, int64(10), *IndeterminantDecisionsCountRef())
-
-       // Test IncrementPermitDecisionsCount and PermitDecisionsCountRef
-       PermitDecisionsCount = 0
-       wg.Add(15)
-       for i := 0; i < 15; i++ {
-               go func() {
-                       defer wg.Done()
-                       IncrementPermitDecisionsCount()
-               }()
-       }
-       wg.Wait()
-       assert.Equal(t, int64(15), *PermitDecisionsCountRef())
-
-       // Test IncrementDenyDecisionsCount and DenyDecisionsCountRef
-       DenyDecisionsCount = 0
-       wg.Add(20)
-       for i := 0; i < 20; i++ {
-               go func() {
-                       defer wg.Done()
-                       IncrementDenyDecisionsCount()
-               }()
-       }
-       wg.Wait()
-       assert.Equal(t, int64(20), *DenyDecisionsCountRef())
-
        // Test IncrementTotalErrorCount and TotalErrorCountRef
        TotalErrorCount = 0
        wg.Add(5)
@@ -79,7 +43,7 @@ func TestCounters(t *testing.T) {
 
        // Test IncrementQuerySuccessCount and TotalQuerySuccessCountRef
 
-       QuerySuccessCount = 0
+       DecisionSuccessCount = 0
 
        wg.Add(7)
 
@@ -89,7 +53,7 @@ func TestCounters(t *testing.T) {
 
                        defer wg.Done()
 
-                       IncrementQuerySuccessCount()
+                       IncrementDecisionSuccessCount()
 
                }()
 
@@ -97,11 +61,11 @@ func TestCounters(t *testing.T) {
 
        wg.Wait()
 
-       assert.Equal(t, int64(7), *TotalQuerySuccessCountRef())
+       assert.Equal(t, int64(7), *TotalDecisionSuccessCountRef())
 
-       // Test IncrementQueryFailureCount and TotalQueryFailureCountRef
+       // Test IncrementDecisionFailureCount and TotalDecisionFailureCountRef
 
-       QueryFailureCount = 0
+       DecisionFailureCount = 0
 
        wg.Add(3)
 
@@ -111,7 +75,7 @@ func TestCounters(t *testing.T) {
 
                        defer wg.Done()
 
-                       IncrementQueryFailureCount()
+                       IncrementDecisionFailureCount()
 
                }()
 
@@ -119,6 +83,6 @@ func TestCounters(t *testing.T) {
 
        wg.Wait()
 
-       assert.Equal(t, int64(3), *TotalQueryFailureCountRef())
+       assert.Equal(t, int64(3), *TotalDecisionFailureCountRef())
 
 }
index ba55b27..9b34839 100644 (file)
@@ -1,6 +1,6 @@
 // -
 //   ========================LICENSE_START=================================
-//   Copyright (C) 2024: Deutsche Telekom
+//   Copyright (C) 2024-2025: Deutsche Telekom
 //
 //   Licensed under the Apache License, Version 2.0 (the "License");
 //   you may not use this file except in compliance with the License.
@@ -17,8 +17,7 @@
 //   ========================LICENSE_END===================================
 //
 
-// Handles an HTTP request to fetch the current system statistics.
-// It aggregates various decision counts (e.g., indeterminate, permit, deny)
+// Handles an HTTP request to fetch the current system statistics
 // and error counts into a structured response and sends it back to the client in JSON format.
 package metrics
 
@@ -58,12 +57,9 @@ func FetchCurrentStatistics(res http.ResponseWriter, req *http.Request) {
 
        var statReport oapicodegen.StatisticsReport
 
-       statReport.IndeterminantDecisionsCount = IndeterminantDecisionsCountRef()
-       statReport.PermitDecisionsCount = PermitDecisionsCountRef()
-       statReport.DenyDecisionsCount = DenyDecisionsCountRef()
+       statReport.DecisionSuccessCount = TotalDecisionSuccessCountRef()
+       statReport.DecisionFailureCount = TotalDecisionFailureCountRef()
        statReport.TotalErrorCount = TotalErrorCountRef()
-       statReport.QuerySuccessCount = TotalQuerySuccessCountRef()
-       statReport.QueryFailureCount = TotalQueryFailureCountRef()
 
        // not implemented hardcoding the values to zero
        // will be implemeneted in phase-2
@@ -81,6 +77,9 @@ func FetchCurrentStatistics(res http.ResponseWriter, req *http.Request) {
 
        res.Header().Set("Content-Type", "application/json")
        res.WriteHeader(http.StatusOK)
-       json.NewEncoder(res).Encode(statReport)
-
+       if err := json.NewEncoder(res).Encode(statReport); err != nil {
+               log.Errorf("Failed to encode JSON response: %v", err)
+               http.Error(res, "Internal Server Error", http.StatusInternalServerError)
+               return
+       }
 }
index 6f90182..cf745a2 100644 (file)
@@ -31,9 +31,6 @@ import (
 
 func TestFetchCurrentStatistics(t *testing.T) {
 
-       IndeterminantDecisionsCount = 10
-       PermitDecisionsCount = 15
-       DenyDecisionsCount = 20
        TotalErrorCount = 5
 
        // Create a new HTTP request
@@ -55,9 +52,6 @@ func TestFetchCurrentStatistics(t *testing.T) {
        assert.NoError(t, err)
 
        // Verify the response body
-       assert.Equal(t, int64(10), *statReport.IndeterminantDecisionsCount)
-       assert.Equal(t, int64(15), *statReport.PermitDecisionsCount)
-       assert.Equal(t, int64(20), *statReport.DenyDecisionsCount)
        assert.Equal(t, int64(5), *statReport.TotalErrorCount)
        assert.Equal(t, int64(0), *statReport.TotalPoliciesCount)
        assert.Equal(t, int64(1), *statReport.TotalPolicyTypesCount)
index b6dc75e..e90b94b 100644 (file)
@@ -15,43 +15,20 @@ const (
 
 // Defines values for ErrorResponseResponseCode.
 const (
-       BADGATEWAY                    ErrorResponseResponseCode = "BAD_GATEWAY"
-       BADREQUEST                    ErrorResponseResponseCode = "BAD_REQUEST"
-       CONFLICT                      ErrorResponseResponseCode = "CONFLICT"
-       EXPECTATIONFAILED             ErrorResponseResponseCode = "EXPECTATION_FAILED"
-       GATEWAYTIMEOUT                ErrorResponseResponseCode = "GATEWAY_TIMEOUT"
-       GONE                          ErrorResponseResponseCode = "GONE"
-       HTTPVERSIONNOTSUPPORTED       ErrorResponseResponseCode = "HTTP_VERSION_NOT_SUPPORTED"
-       INTERNALSERVERERROR           ErrorResponseResponseCode = "INTERNAL_SERVER_ERROR"
-       LENGTHREQUIRED                ErrorResponseResponseCode = "LENGTH_REQUIRED"
-       METHODNOTALLOWED              ErrorResponseResponseCode = "METHOD_NOT_ALLOWED"
-       NETWORKAUTHENTICATIONREQUIRED ErrorResponseResponseCode = "NETWORK_AUTHENTICATION_REQUIRED"
-       NOTACCEPTABLE                 ErrorResponseResponseCode = "NOT_ACCEPTABLE"
-       NOTIMPLEMENTED                ErrorResponseResponseCode = "NOT_IMPLEMENTED"
-       PRECONDITIONFAILED            ErrorResponseResponseCode = "PRECONDITION_FAILED"
-       PRECONDITIONREQUIRED          ErrorResponseResponseCode = "PRECONDITION_REQUIRED"
-       REQUESTEDRANGENOTSATISFIABLE  ErrorResponseResponseCode = "REQUESTED_RANGE_NOT_SATISFIABLE"
-       REQUESTENTITYTOOLARGE         ErrorResponseResponseCode = "REQUEST_ENTITY_TOO_LARGE"
-       REQUESTHEADERFIELDSTOOLARGE   ErrorResponseResponseCode = "REQUEST_HEADER_FIELDS_TOO_LARGE"
-       REQUESTTIMEOUT                ErrorResponseResponseCode = "REQUEST_TIMEOUT"
-       REQUESTURITOOLONG             ErrorResponseResponseCode = "REQUEST_URI_TOO_LONG"
-       SERVICEUNAVAILABLE            ErrorResponseResponseCode = "SERVICE_UNAVAILABLE"
-       TOOMANYREQUESTS               ErrorResponseResponseCode = "TOO_MANY_REQUESTS"
-       UNAUTHORIZED                  ErrorResponseResponseCode = "UNAUTHORIZED"
-       UNSUPPORTEDMEDIATYPE          ErrorResponseResponseCode = "UNSUPPORTED_MEDIA_TYPE"
-)
-
-// Defines values for OPADecisionResponseDecision.
-const (
-       DENY          OPADecisionResponseDecision = "DENY"
-       INDETERMINATE OPADecisionResponseDecision = "INDETERMINATE"
-       NOTAPPLICABLE OPADecisionResponseDecision = "NOTAPPLICABLE"
-       PERMIT        OPADecisionResponseDecision = "PERMIT"
+       BadRequest        ErrorResponseResponseCode = "bad_request"
+       EvaluationError   ErrorResponseResponseCode = "evaluation_error"
+       InternalError     ErrorResponseResponseCode = "internal_error"
+       InvalidOperation  ErrorResponseResponseCode = "invalid_operation"
+       InvalidParameter  ErrorResponseResponseCode = "invalid_parameter"
+       OpaUndefinedError ErrorResponseResponseCode = "opa_undefined_error"
+       ResourceConflict  ErrorResponseResponseCode = "resource_conflict"
+       ResourceNotFound  ErrorResponseResponseCode = "resource_not_found"
+       Unauthorized      ErrorResponseResponseCode = "unauthorized"
+       UndefinedDocument ErrorResponseResponseCode = "undefined_document"
 )
 
 // ErrorResponse defines model for ErrorResponse.
 type ErrorResponse struct {
-       ErrorDetails *[]string                  `json:"errorDetails,omitempty"`
        ErrorMessage *string                    `json:"errorMessage,omitempty"`
        PolicyName   *string                    `json:"policyName,omitempty"`
        ResponseCode *ErrorResponseResponseCode `json:"responseCode,omitempty"`
@@ -71,15 +48,15 @@ type HealthCheckReport struct {
 
 // OPADecisionRequest defines model for OPADecisionRequest.
 type OPADecisionRequest struct {
-       CurrentDate     *openapi_types.Date     `json:"currentDate,omitempty"`
-       CurrentDateTime *time.Time              `json:"currentDateTime,omitempty"`
-       CurrentTime     *time.Time              `json:"currentTime,omitempty"`
-       Input           *map[string]interface{} `json:"input,omitempty"`
-       OnapComponent   *string                 `json:"onapComponent,omitempty"`
-       OnapInstance    *string                 `json:"onapInstance,omitempty"`
-       OnapName        *string                 `json:"onapName,omitempty"`
-       PolicyFilter    *[]string               `json:"policyFilter,omitempty"`
-       PolicyName      *string                 `json:"policyName,omitempty"`
+       CurrentDate     *openapi_types.Date    `json:"currentDate,omitempty"`
+       CurrentDateTime *time.Time             `json:"currentDateTime,omitempty"`
+       CurrentTime     *string                `json:"currentTime,omitempty"`
+       Input           map[string]interface{} `json:"input"`
+       OnapComponent   *string                `json:"onapComponent,omitempty"`
+       OnapInstance    *string                `json:"onapInstance,omitempty"`
+       OnapName        *string                `json:"onapName,omitempty"`
+       PolicyFilter    []string               `json:"policyFilter"`
+       PolicyName      string                 `json:"policyName"`
 
        // TimeOffset Time offset in hours and minutes, e.g., '+02:00' or '-05:00'
        TimeOffset *string `json:"timeOffset,omitempty"`
@@ -90,30 +67,23 @@ type OPADecisionRequest struct {
 
 // OPADecisionResponse defines model for OPADecisionResponse.
 type OPADecisionResponse struct {
-       Decision      *OPADecisionResponseDecision `json:"decision,omitempty"`
-       Output        *map[string]interface{}      `json:"output,omitempty"`
-       PolicyName    *string                      `json:"policyName,omitempty"`
-       StatusMessage *string                      `json:"statusMessage,omitempty"`
+       Output        map[string]interface{} `json:"output"`
+       PolicyName    string                 `json:"policyName"`
+       StatusMessage *string                `json:"statusMessage,omitempty"`
 }
 
-// OPADecisionResponseDecision defines model for OPADecisionResponse.Decision.
-type OPADecisionResponseDecision string
-
 // StatisticsReport defines model for StatisticsReport.
 type StatisticsReport struct {
-       Code                        *int32 `json:"code,omitempty"`
-       DenyDecisionsCount          *int64 `json:"denyDecisionsCount,omitempty"`
-       DeployFailureCount          *int64 `json:"deployFailureCount,omitempty"`
-       DeploySuccessCount          *int64 `json:"deploySuccessCount,omitempty"`
-       IndeterminantDecisionsCount *int64 `json:"indeterminantDecisionsCount,omitempty"`
-       PermitDecisionsCount        *int64 `json:"permitDecisionsCount,omitempty"`
-       QueryFailureCount           *int64 `json:"queryFailureCount,omitempty"`
-       QuerySuccessCount           *int64 `json:"querySuccessCount,omitempty"`
-       TotalErrorCount             *int64 `json:"totalErrorCount,omitempty"`
-       TotalPoliciesCount          *int64 `json:"totalPoliciesCount,omitempty"`
-       TotalPolicyTypesCount       *int64 `json:"totalPolicyTypesCount,omitempty"`
-       UndeployFailureCount        *int64 `json:"undeployFailureCount,omitempty"`
-       UndeploySuccessCount        *int64 `json:"undeploySuccessCount,omitempty"`
+       Code                  *int32 `json:"code,omitempty"`
+       DecisionFailureCount  *int64 `json:"decisionFailureCount,omitempty"`
+       DecisionSuccessCount  *int64 `json:"decisionSuccessCount,omitempty"`
+       DeployFailureCount    *int64 `json:"deployFailureCount,omitempty"`
+       DeploySuccessCount    *int64 `json:"deploySuccessCount,omitempty"`
+       TotalErrorCount       *int64 `json:"totalErrorCount,omitempty"`
+       TotalPoliciesCount    *int64 `json:"totalPoliciesCount,omitempty"`
+       TotalPolicyTypesCount *int64 `json:"totalPolicyTypesCount,omitempty"`
+       UndeployFailureCount  *int64 `json:"undeployFailureCount,omitempty"`
+       UndeploySuccessCount  *int64 `json:"undeploySuccessCount,omitempty"`
 }
 
 // DecisionParams defines parameters for Decision.
index 51cdcf0..96f4eed 100644 (file)
 
 ## Verification API Calls
 
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"example/allow","input":{"method":"POST","path":["users"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22", "currentTime": "11:34:56", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z", "policyFilter" : [""], "policyName":"example","input":{"method":"POST","path":["users"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
 
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z", "policyName":"role/allow","input":{"user":"alice","action":"write","object":"id123","type":"dog"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+{"output":{"allow":true},"policyName":"example"}
 
-## PERMIT for policy:action
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22", "currentTime": "11:34:56", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z", "policyName":"role", "policyFilter": ["role_grants"], "input":{"user":"alice","action":"write","object":"id123","type":"dog"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
 
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"action/allow","input":{"user":"alice","action":"delete","type":"server"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+{"output":{"role_grants":{"billing":[{"action":"read","type":"finance"},{"action":"update","type":"finance"}],"customer":[{"action":"read","type":"dog"},{"action":"read","type":"cat"},{"action":"adopt","type":"dog"},{"action":"adopt","type":"cat"}],"employee":[{"action":"read","type":"dog"},{"action":"read","type":"cat"},{"action":"update","type":"dog"},{"action":"update","type":"cat"}]}},"policyName":"role"}
 
-{"decision":"PERMIT","policyName":"action/allow","statusMessage":"OPA Allowed"}
+## OUTPUT for policy:action with filter role_permissions
 
-## DENY for policy:action
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "11:34:56", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z",__"policyFilter": ["role_permissions"]__, "policyName":"action","input":{"user":"alice","action":"delete","type":"server"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
 
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"action/allow","input":{"user":"charlie","action":"delete","type":"server"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+{"output":{"role_permissions":{"admin":{"actions":["read","write","delete"],"resources":["server","database"]},"editor":{"actions":["read","write"],"resources":["server"]},"viewer":{"actions":["read"],"resources":["server"]}}},"policyName":"action"}
 
-{"decision":"DENY","policyName":"action/allow","statusMessage":"OPA Denied"}
+## OUTPUT for policy:action with empty filters
 
-## PERMIT for policy:account
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "11:34:56", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z",__"policyFilter": [""]__, "policyName":"action","input":{"user":"alice","action":"delete","type":"server"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
 
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC","timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"account/allow", "input":{"creditor_account":11111,"creditor":"alice","debtor_account":22222,"debtor":"bob","period":30,"amount":1000}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+{"output":{"allow":true,"role_permissions":{"admin":{"actions":["read","write","delete"],"resources":["server","database"]},"editor":{"actions":["read","write"],"resources":["server"]},"viewer":{"actions":["read"],"resources":["server"]}},"user_roles":{"alice":["admin"],"bob":["editor"],"charlie":["viewer"]}},"policyName":"action"}
 
-{"decision":"PERMIT","policyName":"account/allow","statusMessage":"OPA Allowed"}
+## OUTPUT for policy:action without filter
 
-## DENY for policy:account
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "11:34:56", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"action","input":{"user":"charlie","action":"delete","type":"server"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
 
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"account/allow", "input":{"creditor_account":11111,"creditor":"alice","debtor_account":22222,"debtor":"bob","period":31,"amount":1000}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+{"errorMessage":"Policy Filter is nil.","policyName":"","responseCode":"bad_request"}
 
-{"decision":"DENY","policyName":"account/allow","statusMessage":"OPA Denied"}
+## OUTPUT for policy:account with filter account_attributes
 
-## PERMIT for policy:organization
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "11:34:56", "timeZone": "UTC","timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z",__"policyFilter": ["account_attributes"]__, "policyName":"account", "input":{"creditor_account":11111,"creditor":"alice","debtor_account":22222,"debtor":"bob","period":30,"amount":1000}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
 
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"organization/allow", "input":{"user":"alice","action": "read","component": "component_A","project": "project_A", "organization": "org_A"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-{"decision":"PERMIT","policyName":"organization/allow","statusMessage":"OPA Allowed"}
+{"output":{"account_attributes":{"11111":{"amount":10000,"owner":"alice"},"22222":{"amount":10000,"owner":"bob"},"33333":{"amount":10000,"owner":"cam"}}},"policyName":"account"}
 
-## DENY for policy:organization
+## OUTPUT for policy:account with empty filter
 
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"organization/allow", "input":{"user":"charlie","action": "edit","component": "component_A","project": "project_A", "organization": "org_A"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "11:34:56", "timeZone": "UTC","timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z",__"policyFilter": [""]__, "policyName":"account", "input":{"creditor_account":11111,"creditor":"alice","debtor_account":22222,"debtor":"bob","period":30,"amount":1000}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
 
-{"decision":"DENY","policyName":"organization/allow","statusMessage":"OPA Denied"}
+{"output":{"account_attributes":{"11111":{"amount":10000,"owner":"alice"},"22222":{"amount":10000,"owner":"bob"},"33333":{"amount":10000,"owner":"cam"}},"allow":true,"amount_is_valid":true,"creditor_is_valid":true,"debtor_is_valid":true,"period_is_valid":true},"policyName":"account"}
 
-## DENY for policy:abac(output)
+## OUTPUT for policy:organization with filter acls
 
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"abac", "policyFilter": ["action_is_read"], "input":{"actions": ["write"],"datatypes": ["location","temperature","precipitation","windspeed"],"time_period": {"from": "2024-03-27","to": "2024-03-31"}}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-{"decision":"DENY","output":{},"policyName":"abac","statusMessage":"OPA Denied"}
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "11:34:56", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z",__"policyFilter": ["acls"]__, "policyName":"organization", "input":{"user":"alice","action": "read","component": "component_A","project": "project_A", "organization": "org_A"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
 
-## PERMIT for policy:abac
+{"output":{"acls":[{"actions":["edit","read"],"component":"component_A","organization":"org_A","project":"project_A","user":"alice"},{"actions":["read"],"organization":"org_A","user":"bob"},{"action":["edit"],"component":"component_A","organization":"org_A","project":"project_B","user":"bob"},{"action":["read"],"organization":"org_A","project":"project_B","user":"charlie"}]},"policyName":"organization"}
 
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"abac", "policyFilter": ["viewable_sensor_data"], "input":{"actions": ["read"],"datatypes": ["location","temperature","precipitation","windspeed"],"time_period": {"from": "2024-02-27","to": "2024-02-29"}}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-{"decision":"PERMIT","output":{"viewable_sensor_data":[{"location":"Galle","precipitation":"500 mm","temperature":"35 C","windspeed":"7.2 m/s"},{"location":"Jaffna","precipitation":"300 mm","temperature":"-5 C","windspeed":"3.8 m/s"},{"location":"Nuwara Eliya","precipitation":"600 mm","temperature":"25 C","windspeed":"4.0 m/s"},{"location":"Trincomalee","precipitation":"1000 mm","temperature":"20 C","windspeed":"5.0 m/s"}]},"policyName":"abac","statusMessage":"OPA Allowed"}
+## OUTPUT for policy:organization with empty filter
 
-## PERMIT for policy:zone
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"zone", "policyFilter": ["has_zone_access"], "input":{"actions": ["view"],"log_id": "log1", "datatypes": ["access", "user"],"time_period": {"from": "2024-11-01T09:00:00Z","to": "2024-11-01T10:00:00Z"},"zone_id": "zoneA"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-{"decision":"PERMIT","output":{"has_zone_access":[{"access":"granted","user":"user1"}]},"policyName":"zone","statusMessage":"OPA Allowed"}
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "11:34:56", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z",__"policyFilter": [""]__, "policyName":"organization", "input":{"user":"alice","action": "read","component": "component_A","project": "project_A", "organization": "org_A"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
 
-## DENY for policy: zone
+{"output":{"acls":[{"actions":["edit","read"],"component":"component_A","organization":"org_A","project":"project_A","user":"alice"},{"actions":["read"],"organization":"org_A","user":"bob"},{"action":["edit"],"component":"component_A","organization":"org_A","project":"project_B","user":"bob"},{"action":["read"],"organization":"org_A","project":"project_B","user":"charlie"}],"allow":true},"policyName":"organization"}
 
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"zone", "policyFilter": ["has_zone_access"], "input":{"actions": ["edit"],"log_id": "log1", "datatypes": ["access", "user"],"time_period": {"from": "2024-11-01T00:00:00Z","to": "2024-11-01T00:00:00Z"},"zone_id": "zoneA"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-{"decision":"DENY","output":{"has_zone_access":[]},"policyName":"zone","statusMessage":"OPA Denied"}
+## OUTPUT for policy:abac with filter viewable_sensor_data
 
-## PERMIT for policy:vehicle
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"abac", __"policyFilter": ["viewable_sensor_data"]__, "input":{"actions": ["write"],"datatypes": ["location","temperature","precipitation","windspeed"],"time_period": {"from": "2024-03-27","to": "2024-03-31"}}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
 
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"vehicle", "policyFilter": ["user_has_vehicle_access"], "input":{"actions": ["use"],"user":"user1", "vehicle_id": "v1", "attributes": ["type", "status"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+{"output":{"viewable_sensor_data":[]},"policyName":"abac"}
 
-{"decision":"PERMIT","output":{"user_has_vehicle_access":[{"status":"available","type":"car"}]},"policyName":"vehicle","statusMessage":"OPA Allowed"}
+## OUTPUT for policy:abac with empty filter
 
-## PERMIT for policy:docs
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"abac", __"policyFilter": [""]__, "input":{"actions": ["write"],"datatypes": ["location","temperature","precipitation","windspeed"],"time_period": {"from": "2024-03-27","to": "2024-03-31"}}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
 
-`curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"docs", "policyFilter": ["has_access_to_file"], "input":{"action": "read","file_id": "file1","access_level": "admin","attributes": ["owner", "size"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+{"output":{"allow":false,"sensor_data":[{"humidity":"40%","id":"0001","location":"Sri Lanka","particle_density":"1.3 g/l","precipitation":"1000 mm","temperature":"28 C","timestamp":"2024-02-26","windspeed":"5.5 m/s"},{"humidity":"45%","id":"0002","location":"Colombo","particle_density":"1.5 g/l","precipitation":"1200 mm","temperature":"30 C","timestamp":"2024-02-26","windspeed":"6.0 m/s"},{"humidity":"60%","id":"0003","location":"Kandy","particle_density":"1.1 g/l","precipitation":"800 mm","temperature":"25 C","timestamp":"2024-02-26","windspeed":"4.5 m/s"},{"humidity":"30%","id":"0004","location":"Galle","particle_density":"1.8 g/l","precipitation":"500 mm","temperature":"35 C","timestamp":"2024-02-27","windspeed":"7.2 m/s"},{"humidity":"20%","id":"0005","location":"Jaffna","particle_density":"0.9 g/l","precipitation":"300 mm","temperature":"-5 C","timestamp":"2024-02-27","windspeed":"3.8 m/s"},{"humidity":"55%","id":"0006","location":"Trincomalee","particle_density":"1.2 g/l","precipitation":"1000 mm","temperature":"20 C","timestamp":"2024-02-28","windspeed":"5.0 m/s"},{"humidity":"50%","id":"0007","location":"Nuwara Eliya","particle_density":"1.3 g/l","precipitation":"600 mm","temperature":"25 C","timestamp":"2024-02-28","windspeed":"4.0 m/s"},{"humidity":"40%","id":"0008","location":"Anuradhapura","particle_density":"1.4 g/l","precipitation":"700 mm","temperature":"28 C","timestamp":"2024-02-29","windspeed":"5.8 m/s"},{"humidity":"65%","id":"0009","location":"Matara","particle_density":"1.6 g/l","precipitation":"900 mm","temperature":"32 C","timestamp":"2024-02-29","windspeed":"6.5 m/s"}],"viewable_sensor_data":[]},"policyName":"abac"}
 
-{"decision":"PERMIT","output":{"has_access_to_file":[{"owner":"user1","size":"10MB"}]},"policyName":"docs","statusMessage":"OPA Allowed"}`
+## OUTPUT for policy:zone with filter has_zone_access
 
-## DENY for policy:docs
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"zone", __"policyFilter": ["has_zone_access"]__, "input":{"actions": ["view"],"log_id": "log1", "datatypes": ["access", "user"],"time_period": {"from": "2024-11-01T09:00:00Z","to": "2024-11-01T10:00:00Z"},"zone_id": "zoneA"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
 
-`curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"docs", "policyFilter": ["has_access_to_file"], "input":{"action": "view","file_id": "file1","access_level": "employee","attributes": ["owner", "size"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+{"output":{"has_zone_access":[{"access":"granted","user":"user1"}]},"policyName":"zone"}
+
+## OUTPUT for policy:zone with empty filter
+
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"zone", __"policyFilter": [""]__, "input":{"actions": ["view"],"log_id": "log1", "datatypes": ["access", "user"],"time_period": {"from": "2024-11-01T09:00:00Z","to": "2024-11-01T10:00:00Z"},"zone_id": "zoneA"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+
+{"output":{"action_is_log_view":true,"allow":true,"has_zone_access":[{"access":"granted","user":"user1"}],"zone":{"zone_access_logs":[{"access":"granted","log_id":"log1","timestamp":"2024-11-01T09:00:00Z","user":"user1","zone_id":"zoneA"},{"access":"denied","log_id":"log2","timestamp":"2024-11-01T10:30:00Z","user":"user2","zone_id":"zoneA"},{"access":"granted","log_id":"log3","timestamp":"2024-11-01T11:00:00Z","user":"user3","zone_id":"zoneB"}]}},"policyName":"zone"}
+
+## OUTPUT for policy:vehicle with filter user_has_vehicle_access
+
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"vehicle", __"policyFilter": ["user_has_vehicle_access"]__, "input":{"actions": ["use"],"user":"user1", "vehicle_id": "v1", "attributes": ["type", "status"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+
+{"output":{"user_has_vehicle_access":[{"status":"available","type":"car"}]},"policyName":"vehicle"}
+
+## OUTPUT for policy:vehicle with empty filter
+
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"vehicle", __"policyFilter": [""]__, "input":{"actions": ["use"],"user":"user1", "vehicle_id": "v1", "attributes": ["type", "status"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+
+{"output":{"action_is_granted":true,"allow":true,"user_has_vehicle_access":[{"status":"available","type":"car"}],"vehicles":[{"owner":"user1","status":"available","type":"car","vehicle_id":"v1"},{"owner":"user2","status":"in use","type":"bike","vehicle_id":"v2"}]},"policyName":"vehicle"}
+
+## OUTPUT for policy:docs with filter has_access_to_file
+
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"docs", __"policyFilter": ["has_access_to_file"]__, "input":{"action": "read","file_id": "file1","access_level": "admin","attributes": ["owner", "size"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+
+{"output":{"has_access_to_file":[{"owner":"user1","size":"10MB"}]},"policyName":"docs"}
+
+## OUTPUT for policy:docs with empty filter
+
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"docs", __"policyFilter": [""]__, "input":{"action": "read","file_id": "file1","access_level": "admin","attributes": ["owner", "size"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+
+{"output":{"action_is_read_or_write":true,"allow":true,"files":[{"access_level":"admin","file_id":"file1","owner":"user1","size":"10MB"},{"access_level":"user","file_id":"file2","owner":"user2","size":"5MB"}],"has_access_to_file":[{"owner":"user1","size":"10MB"}]},"policyName":"docs"}
 
-{"decision":"DENY","output":{"has_access_to_file":[]},"policyName":"docs","statusMessage":"OPA Denied"}`
 
 
 ## HealthCheck API Call With Response
 
 curl -u 'policyadmin:zb!XztG34' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -X GET http://0.0.0.0:8282/policy/pdpo/v1/healthcheck
 
-{"code":200,"healthy":true,"message":"alive","name":"opa-9f0248ea-807e-45f6-8e0f-935e570b75cc","url":"self"}
+{"code":200,"healthy":true,"message":"alive","name":"opa-ea84b1ff-00de-4bf6-a039-222e4511d0a1","url":"self"}
 
 ## Statistics API Call With Response
 
 curl -u 'policyadmin:zb!XztG34' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -X GET http://0.0.0.0:8282/policy/pdpo/v1/statistics
 
-{"code":200,"denyDecisionsCount":10,"deployFailureCount":0,"deploySuccessCount":0,"indeterminantDecisionsCount":0,"permitDecisionsCount":18,"totalErrorCount":4,"totalPoliciesCount":0,"totalPolicyTypesCount":1,"undeployFailureCount":0,"undeploySuccessCount":0}
+{"code":200,"decisionFailureCount":0,"decisionSuccessCount":9,"deployFailureCount":0,"deploySuccessCount":0,"totalErrorCount":5,"totalPoliciesCount":0,"totalPolicyTypesCount":1,"undeployFailureCount":0,"undeploySuccessCount":0}
diff --git a/version b/version
index 51f7e73..276823b 100644 (file)
--- a/version
+++ b/version
@@ -1 +1 @@
-1.0.1-SNAPSHOT
+1.0.2-SNAPSHOT
index 266427f..359ebb9 100644 (file)
@@ -4,7 +4,7 @@
 
 major=1
 minor=0
-patch=1
+patch=2
 
 base_version=${major}.${minor}.${patch}