import (
"fmt"
+ "github.com/google/uuid"
log "github.com/sirupsen/logrus"
"os"
"regexp"
"strconv"
- "github.com/google/uuid"
)
// LogLevel - The log level for the application.
LogLevel = getEnv("LOG_LEVEL", "info")
BootstrapServer = getEnv("KAFKA_URL", "kafka:9092")
Topic = getEnv("PAP_TOPIC", "policy-pdp-pap")
- GroupId = getEnv("GROUPID", "opa-pdp-" + uuid.New().String())
+ GroupId = getEnv("GROUPID", "opa-pdp-"+uuid.New().String())
Username = getEnv("API_USER", "policyadmin")
Password = getEnv("API_PASSWORD", "zb!XztG34")
UseSASLForKAFKA = getEnv("UseSASLForKAFKA", "false")
BundleTarGzFile = "/app/bundles/bundle.tar.gz"
PdpGroup = "opaGroup"
//This is a workaround as currently opa-pdp is not defined in the PapDB defaultGroup configuration and creating it manually overrides the existing configuration, so currently PdpGroup is opaGroup and it will be changed to defaultGroup once added in the configuration.
- PdpType = "opa"
- ServerPort = ":8282"
- ServerWaitUpTime = 5
- ShutdownWaitTime = 5
+ PdpType = "opa"
+ ServerPort = ":8282"
+ ServerWaitUpTime = 5
+ ShutdownWaitTime = 5
V1Compatible = "--v1-compatible"
- LatestVersion = "1.0.0"
- MinorVersion = "0"
- PatchVersion = "0"
- OpaPdpUrl = "self"
- HealtCheckStatus = true
- OkCode = int32(200)
- HealthCheckMessage = "alive"
- SingleHierarchy = 4
+ LatestVersion = "1.0.0"
+ MinorVersion = "0"
+ PatchVersion = "0"
+ OpaPdpUrl = "self"
+ HealtCheckStatus = true
+ OkCode = int32(200)
+ HealthCheckMessage = "alive"
+ SingleHierarchy = 4
)
validationErrors := utils.ValidateOPADataRequest(decisionReq)
if decisionReq.PolicyFilter == nil || len(decisionReq.PolicyFilter) == 0 {
- validationErrors = append(validationErrors, "PolicyFilter is required and cannot be empty")
+ validationErrors = append(validationErrors, "PolicyFilter is required")
}
if len(validationErrors) > 0 {
*errorDtls = strings.Join(validationErrors, ", ")
validFilters := getValidPolicyFilters(result)
for _, filter := range filters {
+ if filter == "" {
+ // when filter is "" empty, the entire resultant data will be reported
+ return result, nil, validFilters
+ }
// Try to find the value in the result map
if value := findNestedValue(result, strings.Split(filter, "/")); value != nil {
filteredOutput[filter] = value // Store using full path
OpaDecision(rec, req)
assert.Equal(t, http.StatusBadRequest, rec.Code)
- assert.Contains(t, rec.Body.String(), "PolicyFilter is required and cannot be empty")
+ assert.Contains(t, rec.Body.String(), "PolicyFilter is required")
}
// Test for OPA Instance Error
return nil, nil, err
}
- log.Debugf("Decoded policy content for key '%s': %s", key, decodedPolicy)
+ log.Tracef("Decoded policy content for key '%s': %s", key, decodedPolicy)
}
return decodedPolicies, keys, nil
}
-func TestCreateBundleFunc(t *testing.T){
+func TestCreateBundleFunc(t *testing.T) {
}
package handler
import (
- "encoding/json"
"context"
+ "encoding/json"
"errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
}()
// Mock removeDataDirectoryFunc and deleteDataFunc to return errors for testing
- opasdkGetData =func (ctx context.Context, dataPath string) (data *oapicodegen.OPADataResponse_Data, err error){
+ opasdkGetData = func(ctx context.Context, dataPath string) (data *oapicodegen.OPADataResponse_Data, err error) {
// Mock JSON data
- mockedData := `{"mocked": {"success": "value", "error": "value"}}`
- // Create an instance of OPADataResponse_Data
- var response oapicodegen.OPADataResponse_Data
- // Unmarshal into the OPADataResponse_Data struct
- err = json.Unmarshal([]byte(mockedData), &response)
- if err != nil {
- return nil,errors.New("Error unmarshalling")
+ mockedData := `{"mocked": {"success": "value", "error": "value"}}`
+ // Create an instance of OPADataResponse_Data
+ var response oapicodegen.OPADataResponse_Data
+ // Unmarshal into the OPADataResponse_Data struct
+ err = json.Unmarshal([]byte(mockedData), &response)
+ if err != nil {
+ return nil, errors.New("Error unmarshalling")
+ }
+ return &response, nil //
}
- return &response, nil //
-}
removeDataDirectoryFunc = func(dataKey string) error {
if dataKey == "/mocked/error" {
return errors.New("mocked remove data directory error")
}
// Close closes the KafkaConsumer
-func (kc *KafkaConsumer) Close() error{
+func (kc *KafkaConsumer) Close() error {
if kc.Consumer != nil {
- if err := kc.Consumer.Close(); err != nil{
+ if err := kc.Consumer.Close(); err != nil {
return fmt.Errorf("failed to close consumer: %v", err)
}
}
}
type KafkaNewConsumerFunc func(*kafka.ConfigMap) (*kafka.Consumer, error)
+
var KafkaNewConsumer KafkaNewConsumerFunc = kafka.NewConsumer
-// NewKafkaConsumer creates a new Kafka consumer and returns
+// NewKafkaConsumer creates a new Kafka consumer and returns
func NewKafkaConsumer() (*KafkaConsumer, error) {
// Initialize the consumer instance only once
consumerOnce.Do(func() {
fmt.Print(configMap)
// If SASL is enabled, add SASL properties
if useSASL == "true" {
- configMap.SetKey("sasl.mechanism", "SCRAM-SHA-512") // #nosec G104
- configMap.SetKey("sasl.username", username) // #nosec G104
- configMap.SetKey("sasl.password", password) // #nosec G104
- configMap.SetKey("security.protocol", "SASL_PLAINTEXT") // #nosec G104
- configMap.SetKey("fetch.max.bytes", 50*1024*1024) // #nosec G104
- configMap.SetKey("max.partition.fetch.bytes",50*1024*1024) // #nosec G104
- configMap.SetKey("socket.receive.buffer.bytes", 50*1024*1024) // #nosec G104
- configMap.SetKey("session.timeout.ms", "30000") // #nosec G104
- configMap.SetKey("max.poll.interval.ms", "300000") // #nosec G104
- configMap.SetKey("enable.partition.eof", true) // #nosec G104
- configMap.SetKey("enable.auto.commit", true) // #nosec G104
+ configMap.SetKey("sasl.mechanism", "SCRAM-SHA-512") // #nosec G104
+ configMap.SetKey("sasl.username", username) // #nosec G104
+ configMap.SetKey("sasl.password", password) // #nosec G104
+ configMap.SetKey("security.protocol", "SASL_PLAINTEXT") // #nosec G104
+ configMap.SetKey("fetch.max.bytes", 50*1024*1024) // #nosec G104
+ configMap.SetKey("max.partition.fetch.bytes", 50*1024*1024) // #nosec G104
+ configMap.SetKey("socket.receive.buffer.bytes", 50*1024*1024) // #nosec G104
+ configMap.SetKey("session.timeout.ms", "30000") // #nosec G104
+ configMap.SetKey("max.poll.interval.ms", "300000") // #nosec G104
+ configMap.SetKey("enable.partition.eof", true) // #nosec G104
+ configMap.SetKey("enable.auto.commit", true) // #nosec G104
// configMap.SetKey("debug", "all") // Uncomment for debug
}
import (
"errors"
- "fmt"
+ "fmt"
"github.com/confluentinc/confluent-kafka-go/v2/kafka"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
}
func TestKafkaConsumerClose_Error(t *testing.T) {
- mockConsumer := new(mocks.KafkaConsumerInterface)
+ mockConsumer := new(mocks.KafkaConsumerInterface)
- kc := &KafkaConsumer{Consumer: mockConsumer}
+ kc := &KafkaConsumer{Consumer: mockConsumer}
- // Set up the mock for Close
- mockConsumer.On("Close").Return(errors.New("close error"))
+ // Set up the mock for Close
+ mockConsumer.On("Close").Return(errors.New("close error"))
- // Test Close method
- kc.Close()
+ // Test Close method
+ kc.Close()
- // Verify that Close was called
- mockConsumer.AssertExpectations(t)
+ // Verify that Close was called
+ mockConsumer.AssertExpectations(t)
}
func TestKafkaConsumer_Unsubscribe(t *testing.T) {
}
if useSASL == "true" {
- configMap.SetKey("sasl.mechanism", "SCRAM-SHA-512") // #nosec G104
- configMap.SetKey("sasl.username", username) // #nosec G104
- configMap.SetKey("sasl.password", password) // #nosec G104
+ configMap.SetKey("sasl.mechanism", "SCRAM-SHA-512") // #nosec G104
+ configMap.SetKey("sasl.username", username) // #nosec G104
+ configMap.SetKey("sasl.password", password) // #nosec G104
configMap.SetKey("security.protocol", "SASL_PLAINTEXT") // #nosec G104
}
log.Println("KafkaProducer or producer is nil, skipping Close.")
return
}
- kp.producer.Flush(15*1000)
+ kp.producer.Flush(15 * 1000)
kp.producer.Close()
log.Println("KafkaProducer closed successfully.")
}
producer: mockProducer,
}
- mockProducer.On("Flush", mock.AnythingOfType("int")).Return(0)
+ mockProducer.On("Flush", mock.AnythingOfType("int")).Return(0)
// Simulate successful close
mockProducer.On("Close").Return()
Expected Output: Heartbeat message is sent successfully, and a debug log "Message sent successfully" is generated.
*/
func TestSendPDPHeartBeat_SuccessSomeDeployedPolicies(t *testing.T) {
- // Setup mock Policymap
- mockPolicymap := new(MockPolicymap)
+ // Setup mock Policymap
+ mockPolicymap := new(MockPolicymap)
- mockSender := new(mocks.PdpStatusSender)
- mockSender.On("SendPdpStatus", mock.Anything).Return(nil)
+ mockSender := new(mocks.PdpStatusSender)
+ mockSender.On("SendPdpStatus", mock.Anything).Return(nil)
- policymap.LastDeployedPolicies = "some-policies"
- // Set mock behavior for policymap
- mockPolicymap.On("ExtractDeployedPolicies", mock.Anything).Return(nil)
- err := sendPDPHeartBeat(mockSender)
- assert.NoError(t, err)
+ policymap.LastDeployedPolicies = "some-policies"
+ // Set mock behavior for policymap
+ mockPolicymap.On("ExtractDeployedPolicies", mock.Anything).Return(nil)
+ err := sendPDPHeartBeat(mockSender)
+ assert.NoError(t, err)
}
/*
Expected Output: Heartbeat message is sent successfully, and a debug log "Message sent successfully" is generated.
*/
func TestSendPDPHeartBeat_SuccessNoDeployedPolicies(t *testing.T) {
- // Setup mock Policymap
- mockPolicymap := new(MockPolicymap)
+ // Setup mock Policymap
+ mockPolicymap := new(MockPolicymap)
- mockSender := new(mocks.PdpStatusSender)
- mockSender.On("SendPdpStatus", mock.Anything).Return(nil)
+ mockSender := new(mocks.PdpStatusSender)
+ mockSender.On("SendPdpStatus", mock.Anything).Return(nil)
- policymap.LastDeployedPolicies = ""
- // Set mock behavior for policymap
- mockPolicymap.On("ExtractDeployedPolicies", mock.Anything).Return(nil)
- err := sendPDPHeartBeat(mockSender)
- assert.NoError(t, err)
+ policymap.LastDeployedPolicies = ""
+ // Set mock behavior for policymap
+ mockPolicymap.On("ExtractDeployedPolicies", mock.Anything).Return(nil)
+ err := sendPDPHeartBeat(mockSender)
+ assert.NoError(t, err)
}
/*
import (
"errors"
"fmt"
+ "github.com/confluentinc/confluent-kafka-go/v2/kafka"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"policy-opa-pdp/pkg/kafkacomm/publisher/mocks"
- "github.com/confluentinc/confluent-kafka-go/v2/kafka"
"policy-opa-pdp/pkg/model"
"testing"
"time"
}
func (m *MockKafkaProducer) Flush(timeout int) int {
- m.Called(timeout)
+ m.Called(timeout)
return 0
}
mockProducer.On("Produce", mock.Anything).Return(nil)
//t.Fatalf("Inside Sender checking for producer , but got: %v", mockProducer)
-
// Create the RealPdpStatusSender with the mocked producer
sender := RealPdpStatusSender{
Producer: mockProducer,
// Mock Policymap
type MockPolicymap struct {
- mock.Mock
+ mock.Mock
}
func (m *MockPolicymap) ExtractDeployedPolicies(policiesMap string) []model.ToscaConceptIdentifier {
- args := m.Called(policiesMap)
- return args.Get(0).([]model.ToscaConceptIdentifier)
+ args := m.Called(policiesMap)
+ return args.Get(0).([]model.ToscaConceptIdentifier)
}
func (m *MockPolicymap) SetLastDeployedPolicies(policiesMap string) {
- m.Called(policiesMap)
+ m.Called(policiesMap)
}
// TestSendPdpUpdateResponse_Success tests SendPdpUpdateResponse for a successful response
func TestSendPdpUpdateResponse_Success_NoPolicies(t *testing.T) {
mockPolicymap := new(MockPolicymap)
-
- mockSender := new(mocks.PdpStatusSender)
- mockSender.On("SendPdpStatus", mock.Anything).Return(nil)
- pdpUpdate := &model.PdpUpdate{RequestId: "test-request-id"}
+ mockSender := new(mocks.PdpStatusSender)
+ mockSender.On("SendPdpStatus", mock.Anything).Return(nil)
+ pdpUpdate := &model.PdpUpdate{RequestId: "test-request-id"}
policymap.LastDeployedPolicies = ""
- mockPolicymap.On("ExtractDeployedPolicies", mock.Anything).Return(nil)
+ mockPolicymap.On("ExtractDeployedPolicies", mock.Anything).Return(nil)
- err := SendPdpUpdateResponse(mockSender, pdpUpdate, "PDPUpdate Successful")
- assert.NoError(t, err)
- mockSender.AssertCalled(t, "SendPdpStatus", mock.Anything)
+ err := SendPdpUpdateResponse(mockSender, pdpUpdate, "PDPUpdate Successful")
+ assert.NoError(t, err)
+ mockSender.AssertCalled(t, "SendPdpStatus", mock.Anything)
}
// TestSendPdpUpdateResponse_Success tests SendPdpUpdateResponse for a successful response with some policies
func TestSendPdpUpdateResponse_Success_SomeDeployedPolicies(t *testing.T) {
mockPolicymap := new(MockPolicymap)
- mockSender := new(mocks.PdpStatusSender)
- mockSender.On("SendPdpStatus", mock.Anything).Return(nil)
- pdpUpdate := &model.PdpUpdate{RequestId: "test-request-id"}
- policymap.LastDeployedPolicies = "some-policies"
- mockPolicymap.On("ExtractDeployedPolicies", mock.Anything).Return(nil)
- err := SendPdpUpdateResponse(mockSender, pdpUpdate, "PDPUpdate Successful")
- assert.NoError(t, err)
- mockSender.AssertCalled(t, "SendPdpStatus", mock.Anything)
+ mockSender := new(mocks.PdpStatusSender)
+ mockSender.On("SendPdpStatus", mock.Anything).Return(nil)
+ pdpUpdate := &model.PdpUpdate{RequestId: "test-request-id"}
+ policymap.LastDeployedPolicies = "some-policies"
+ mockPolicymap.On("ExtractDeployedPolicies", mock.Anything).Return(nil)
+ err := SendPdpUpdateResponse(mockSender, pdpUpdate, "PDPUpdate Successful")
+ assert.NoError(t, err)
+ mockSender.AssertCalled(t, "SendPdpStatus", mock.Anything)
}
// TestSendPdpUpdateErrorResponse_Success tests SendPdpUpdateResponse
func TestSendPdpUpdateErrorResponse(t *testing.T) {
- mockSender := new(mocks.PdpStatusSender)
- mockSender.On("SendPdpStatus", mock.Anything).Return(errors.New("Sending error response"))
+ mockSender := new(mocks.PdpStatusSender)
+ mockSender.On("SendPdpStatus", mock.Anything).Return(errors.New("Sending error response"))
- pdpUpdate := &model.PdpUpdate{RequestId: "test-request-id"}
+ pdpUpdate := &model.PdpUpdate{RequestId: "test-request-id"}
- mockerr := errors.New("Sending Error response")
- err := SendPdpUpdateErrorResponse(mockSender, pdpUpdate, mockerr)
+ mockerr := errors.New("Sending Error response")
+ err := SendPdpUpdateErrorResponse(mockSender, pdpUpdate, mockerr)
- assert.Error(t, err)
+ assert.Error(t, err)
- mockSender.AssertCalled(t, "SendPdpStatus", mock.Anything)
+ mockSender.AssertCalled(t, "SendPdpStatus", mock.Anything)
}
// TestSendPdpUpdateErrorResponse_Success tests SendPdpUpdateResponse for some policies
func TestSendPdpUpdateErrorResponse_SomeDeployedPolicies(t *testing.T) {
- // Setup mock Policymap
- mockPolicymap := new(MockPolicymap)
-
- mockSender := new(mocks.PdpStatusSender)
- mockSender.On("SendPdpStatus", mock.Anything).Return(errors.New("Sending error response"))
- pdpUpdate := &model.PdpUpdate{RequestId: "test-request-id"}
-
- policymap.LastDeployedPolicies = "some-policies"
- // Set mock behavior for policymap
- mockPolicymap.On("ExtractDeployedPolicies", mock.Anything).Return(nil)
- mockerr := errors.New("Sending Error response")
- err := SendPdpUpdateErrorResponse(mockSender, pdpUpdate, mockerr)
- assert.Error(t, err)
- //mockPolicymap.AssertExpectations(t)
- mockSender.AssertCalled(t, "SendPdpStatus", mock.Anything)
+ // Setup mock Policymap
+ mockPolicymap := new(MockPolicymap)
+
+ mockSender := new(mocks.PdpStatusSender)
+ mockSender.On("SendPdpStatus", mock.Anything).Return(errors.New("Sending error response"))
+ pdpUpdate := &model.PdpUpdate{RequestId: "test-request-id"}
+
+ policymap.LastDeployedPolicies = "some-policies"
+ // Set mock behavior for policymap
+ mockPolicymap.On("ExtractDeployedPolicies", mock.Anything).Return(nil)
+ mockerr := errors.New("Sending Error response")
+ err := SendPdpUpdateErrorResponse(mockSender, pdpUpdate, mockerr)
+ assert.Error(t, err)
+ //mockPolicymap.AssertExpectations(t)
+ mockSender.AssertCalled(t, "SendPdpStatus", mock.Anything)
}
// TestSendPdpUpdateErrorResponse_Success tests SendPdpUpdateResponse for no policies
func TestSendPdpUpdateErrorResponse_NoPolicies(t *testing.T) {
- // Setup mock Policymap
- mockPolicymap := new(MockPolicymap)
-
- mockSender := new(mocks.PdpStatusSender)
- mockSender.On("SendPdpStatus", mock.Anything).Return(errors.New("Sending error response"))
- pdpUpdate := &model.PdpUpdate{RequestId: "test-request-id"}
-
- policymap.LastDeployedPolicies = ""
- // Set mock behavior for policymap
- mockPolicymap.On("ExtractDeployedPolicies", mock.Anything).Return(nil)
- mockerr := errors.New("Sending Error response")
- err := SendPdpUpdateErrorResponse(mockSender, pdpUpdate, mockerr)
- assert.Error(t, err)
- //mockPolicymap.AssertExpectations(t)
- mockSender.AssertCalled(t, "SendPdpStatus", mock.Anything)
+ // Setup mock Policymap
+ mockPolicymap := new(MockPolicymap)
+
+ mockSender := new(mocks.PdpStatusSender)
+ mockSender.On("SendPdpStatus", mock.Anything).Return(errors.New("Sending error response"))
+ pdpUpdate := &model.PdpUpdate{RequestId: "test-request-id"}
+
+ policymap.LastDeployedPolicies = ""
+ // Set mock behavior for policymap
+ mockPolicymap.On("ExtractDeployedPolicies", mock.Anything).Return(nil)
+ mockerr := errors.New("Sending Error response")
+ err := SendPdpUpdateErrorResponse(mockSender, pdpUpdate, mockerr)
+ assert.Error(t, err)
+ //mockPolicymap.AssertExpectations(t)
+ mockSender.AssertCalled(t, "SendPdpStatus", mock.Anything)
}
+
// TestSendStateChangeResponse_Success tests SendStateChangeResponse for a successful state change response
func TestSendStateChangeResponse_Success(t *testing.T) {
- mockSender := new(mocks.PdpStatusSender)
+ mockSender := new(mocks.PdpStatusSender)
mockSender.On("SendPdpStatus", mock.Anything).Return(nil)
pdpStateChange := &model.PdpStateChange{RequestId: "test-state-change-id"}
// Increment counter
func IncrementDeploySuccessCount() {
- mu.Lock()
- DeploySuccessCount++
- mu.Unlock()
+ mu.Lock()
+ DeploySuccessCount++
+ mu.Unlock()
}
// returns pointer to the counter
func totalDeploySuccessCountRef() *int64 {
- mu.Lock()
- defer mu.Unlock()
- return &DeploySuccessCount
+ mu.Lock()
+ defer mu.Unlock()
+ return &DeploySuccessCount
}
// Increment counter
func IncrementDeployFailureCount() {
- mu.Lock()
- DeployFailureCount++
- mu.Unlock()
+ mu.Lock()
+ DeployFailureCount++
+ mu.Unlock()
}
// returns pointer to the counter
func totalDeployFailureCountRef() *int64 {
- mu.Lock()
- defer mu.Unlock()
- return &DeployFailureCount
+ mu.Lock()
+ defer mu.Unlock()
+ return &DeployFailureCount
}
-
// Increment counter
func IncrementUndeploySuccessCount() {
- mu.Lock()
+ mu.Lock()
UndeploySuccessCount++
mu.Unlock()
}
// returns pointer to the counter
func totalUndeploySuccessCountRef() *int64 {
- mu.Lock()
- defer mu.Unlock()
- return &UndeploySuccessCount
+ mu.Lock()
+ defer mu.Unlock()
+ return &UndeploySuccessCount
}
// Increment counter
func IncrementUndeployFailureCount() {
- mu.Lock()
- UndeployFailureCount++
- mu.Unlock()
+ mu.Lock()
+ UndeployFailureCount++
+ mu.Unlock()
}
// returns pointer to the counter
func totalUndeployFailureCountRef() *int64 {
- mu.Lock()
- defer mu.Unlock()
- return &UndeployFailureCount
+ mu.Lock()
+ defer mu.Unlock()
+ return &UndeployFailureCount
}
// Increment counter
func SetTotalPoliciesCount(newCount int64) {
- mu.Lock()
- TotalPoliciesCount = newCount
- mu.Unlock()
+ mu.Lock()
+ TotalPoliciesCount = newCount
+ mu.Unlock()
}
// returns pointer to the counter
func totalPoliciesCountRef() *int64 {
- mu.Lock()
- defer mu.Unlock()
- return &TotalPoliciesCount
+ mu.Lock()
+ defer mu.Unlock()
+ return &TotalPoliciesCount
}
-
assert.Equal(t, int64(3), *TotalDecisionFailureCountRef())
-
-// Test IncrementDeploySuccessCount and totalDeploySuccessCountRef
+ // Test IncrementDeploySuccessCount and totalDeploySuccessCountRef
DeploySuccessCount = 0
wg.Add(4)
for i := 0; i < 4; i++ {
wg.Wait()
assert.Equal(t, int64(4), *totalDeploySuccessCountRef())
-// Test IncrementDeployFailureCount and totalDeployFailureCountRef
+ // Test IncrementDeployFailureCount and totalDeployFailureCountRef
DeployFailureCount = 0
wg.Add(2)
for i := 0; i < 2; i++ {
wg.Wait()
assert.Equal(t, int64(2), *totalDeployFailureCountRef())
-// Test IncrementUndeploySuccessCount and totalUndeploySuccessCountRef
+ // Test IncrementUndeploySuccessCount and totalUndeploySuccessCountRef
UndeploySuccessCount = 0
wg.Add(6)
for i := 0; i < 6; i++ {
wg.Wait()
assert.Equal(t, int64(6), *totalUndeploySuccessCountRef())
-// Test IncrementUndeployFailureCount and totalUndeployFailureCountRef
+ // Test IncrementUndeployFailureCount and totalUndeployFailureCountRef
UndeployFailureCount = 0
wg.Add(1)
for i := 0; i < 1; i++ {
wg.Wait()
assert.Equal(t, int64(1), *totalUndeployFailureCountRef())
-// Test SetTotalPoliciesCount and totalPoliciesCountRef
+ // Test SetTotalPoliciesCount and totalPoliciesCountRef
SetTotalPoliciesCount(15)
assert.Equal(t, int64(15), *totalPoliciesCountRef())
-
}
var statReport oapicodegen.StatisticsReport
-
statReport.DecisionSuccessCount = totalDecisionSuccessCountRef()
statReport.DecisionFailureCount = TotalDecisionFailureCountRef()
- statReport.TotalErrorCount = totalErrorCountRef()
- statReport.DeployFailureCount = totalDeployFailureCountRef()
- statReport.DeploySuccessCount = totalDeploySuccessCountRef()
- statReport.UndeployFailureCount = totalUndeployFailureCountRef()
- statReport.UndeploySuccessCount = totalUndeploySuccessCountRef()
- statReport.TotalPoliciesCount = totalPoliciesCountRef()
+ statReport.TotalErrorCount = totalErrorCountRef()
+ statReport.DeployFailureCount = totalDeployFailureCountRef()
+ statReport.DeploySuccessCount = totalDeploySuccessCountRef()
+ statReport.UndeployFailureCount = totalUndeployFailureCountRef()
+ statReport.UndeploySuccessCount = totalUndeploySuccessCountRef()
+ statReport.TotalPoliciesCount = totalPoliciesCountRef()
// not implemented hardcoding the values to zero
// will be implemeneted in phase-2
)
func TestFetchCurrentStatistics(t *testing.T) {
- TotalErrorCount = 0
+ TotalErrorCount = 0
DecisionSuccessCount = 0
DecisionFailureCount = 0
DeployFailureCount = 0
}
func TestFetchCurrentStatistics_ValidRequestID(t *testing.T) {
- TotalErrorCount = 0
+ TotalErrorCount = 0
DecisionSuccessCount = 0
DecisionFailureCount = 0
DeployFailureCount = 0
Source: "source1",
PdpHeartbeatIntervalMs: 5000,
MessageType: "PDP_UPDATE",
- PoliciesToBeDeployed: policies,
+ PoliciesToBeDeployed: policies,
Name: "ExamplePDP",
TimestampMs: 1633017600000,
PdpGroup: "Group1",
Source: "",
PdpHeartbeatIntervalMs: 5000,
MessageType: "",
- PoliciesToBeDeployed: nil,
+ PoliciesToBeDeployed: nil,
Name: "",
TimestampMs: 0,
PdpGroup: "",
// Define the structs
var (
- opaInstance *sdk.OPA //A singleton instance of the OPA object
- once sync.Once //A sync.Once variable used to ensure that the OPA instance is initialized only once,
- memStore storage.Store
+ opaInstance *sdk.OPA //A singleton instance of the OPA object
+ once sync.Once //A sync.Once variable used to ensure that the OPA instance is initialized only once,
+ memStore storage.Store
UpsertPolicyVar UpsertPolicyFunc = UpsertPolicy
- WriteDataVar WriteDataFunc = WriteData
+ WriteDataVar WriteDataFunc = WriteData
)
type (
- UpsertPolicyFunc func(ctx context.Context, policyID string, policyContent []byte) error
- WriteDataFunc func(ctx context.Context, dataPath string, data interface{}) error
+ UpsertPolicyFunc func(ctx context.Context, policyID string, policyContent []byte) error
+ WriteDataFunc func(ctx context.Context, dataPath string, data interface{}) error
)
type PatchImpl struct {
}
type NewSDKFunc func(ctx context.Context, options sdk.Options) (*sdk.OPA, error)
+
var NewSDK NewSDKFunc = sdk.New
// Returns a singleton instance of the OPA object. The initialization of the instance is
func GetOPASingletonInstance() (*sdk.OPA, error) {
var err error
once.Do(func() {
- var opaErr error
+ var opaErr error
memStore = inmem.New()
- opaInstance, opaErr = NewSDK(context.Background(), sdk.Options{
+ opaInstance, opaErr = NewSDK(context.Background(), sdk.Options{
// Configure your OPA instance here
V1Compatible: true,
Store: memStore,
Config: jsonReader,
})
if err != nil {
- log.Warnf("Failed to configure OPA: %v", err)
+ log.Warnf("Failed to configure OPA: %v", err)
}
}
})
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"io"
+ "net/http"
"net/http/httptest"
"os"
"policy-opa-pdp/consts"
"sync"
"testing"
- "net/http"
)
// Mock for os.Open
res := httptest.NewRecorder()
ListPolicies(res, req)
-// assert.Nil(t, err)
-// assert.NoError(t, err)
+ // assert.Nil(t, err)
+ // assert.NoError(t, err)
mockMemStore.AssertExpectations(t)
}
res := httptest.NewRecorder()
ListPolicies(res, req)
-// assert.NoError(t, err)
+ // assert.NoError(t, err)
mockMemStore.AssertExpectations(t)
}
func ValidateOPADataRequest(request interface{}) []string {
var validationErrors []string
if updateRequest, ok := request.(*oapicodegen.OPADataUpdateRequest); ok {
+ if updateRequest == nil { // Check if updateRequest is nil
+ validationErrors = append(validationErrors, "OPADataUpdateRequest is nil")
+ return validationErrors // Return if the request is nil
+ }
// Check if required fields are populated
- dateString := (updateRequest.CurrentDate).String()
- if !(IsValidCurrentDate(&dateString)) {
+ if updateRequest.CurrentDate != nil {
+ dateString := updateRequest.CurrentDate.String()
+ if !IsValidCurrentDate(&dateString) {
+ validationErrors = append(validationErrors, "CurrentDate is invalid")
+ }
+ } else {
validationErrors = append(validationErrors, "CurrentDate is required")
}
}
if decisionRequest, ok := request.(*oapicodegen.OPADecisionRequest); ok {
+
+ if decisionRequest == nil { // Check if decisionRequest is nil
+ validationErrors = append(validationErrors, "OPADecisionRequest is nil")
+ return validationErrors // Return if the request is nil
+ }
// Check if required fields are populated
- dateString := (decisionRequest.CurrentDate).String()
- if !(IsValidCurrentDate(&dateString)) {
- validationErrors = append(validationErrors, "CurrentDate is required")
+ if decisionRequest.CurrentDate != nil {
+ dateString := decisionRequest.CurrentDate.String()
+ if !IsValidCurrentDate(&dateString) {
+ validationErrors = append(validationErrors, "CurrentDate is invalid")
+ }
}
// Validate CurrentDateTime format
- if !(IsValidTime(decisionRequest.CurrentDateTime)) {
+ if (decisionRequest.CurrentDateTime != nil) && !(IsValidTime(decisionRequest.CurrentDateTime)) {
validationErrors = append(validationErrors, "CurrentDateTime is invalid or missing")
}
// Validate CurrentTime format
- if !(IsValidCurrentTime(decisionRequest.CurrentTime)) {
+ if (decisionRequest.CurrentTime != nil) && !(IsValidCurrentTime(decisionRequest.CurrentTime)) {
validationErrors = append(validationErrors, "CurrentTime is invalid or missing")
}
// Validate TimeOffset format (e.g., +02:00 or -05:00)
- if !(IsValidTimeOffset(decisionRequest.TimeOffset)) {
+ if (decisionRequest.TimeOffset != nil) && !(IsValidTimeOffset(decisionRequest.TimeOffset)) {
validationErrors = append(validationErrors, "TimeOffset is invalid or missing")
}
// Validate TimeZone format (e.g., 'America/New_York')
- if !(IsValidTimeZone(decisionRequest.TimeZone)) {
+ if (decisionRequest.TimeZone != nil) && !(IsValidTimeZone(decisionRequest.TimeZone)) {
validationErrors = append(validationErrors, "TimeZone is invalid or missing")
}
// Optionally, check if 'OnapComponent', 'OnapInstance', 'OnapName', and 'PolicyName' are provided
- if !(IsValidString(decisionRequest.OnapComponent)) {
+ if (decisionRequest.OnapComponent != nil) && !(IsValidString(decisionRequest.OnapComponent)) {
validationErrors = append(validationErrors, "OnapComponent is required")
}
- if !(IsValidString(decisionRequest.OnapInstance)) {
+ if (decisionRequest.OnapInstance != nil) && !(IsValidString(decisionRequest.OnapInstance)) {
validationErrors = append(validationErrors, "OnapInstance is required")
}
- if !(IsValidString(decisionRequest.OnapName)) {
+ if (decisionRequest.OnapName != nil) && !(IsValidString(decisionRequest.OnapName)) {
validationErrors = append(validationErrors, "OnapName is required")
}
}
func TestValidateOPADataRequest(t *testing.T) {
- ctime := "12:00:00"
- timeZone := "America_New_York"
- timeOffset := "$02:00"
- onapComp := " "
- onapIns := " "
- onapName := " "
- policyName := " "
- var currentDate openapi_types.Date
- currentDate = openapi_types.Date{}
- var currentDateTime time.Time
- currentDateTime = time.Time{}
+ ctime := "08:26:41.857Z"
+ onapComp := "COMPONENT"
+ onapIns := "INSTANCE"
+ onapName := "ONAP"
+ policyName := "s3"
+ parsedDate, err := time.Parse("2006-01-02", "2024-02-12")
+ if err != nil {
+ fmt.Println("error in parsedDate")
+ }
+ currentDate := openapi_types.Date{Time: parsedDate}
+ currentDateTime, err := time.Parse(time.RFC3339, "2024-02-12T12:00:00Z")
+ if err != nil {
+ fmt.Println("error in currentDateTime")
+ }
+
+ inValidDecisionRequest := &oapicodegen.OPADecisionRequest{
+ CurrentDate: ¤tDate,
+ CurrentDateTime: ¤tDateTime,
+ }
var data []map[string]interface{}
CurrentDate: ¤tDate,
CurrentDateTime: ¤tDateTime,
CurrentTime: &ctime,
- TimeOffset: &timeOffset,
- TimeZone: &timeZone,
OnapComponent: &onapComp,
OnapInstance: &onapIns,
OnapName: &onapName,
Data: &data,
}
- inValidErr := []string{"CurrentTime is invalid or missing", "TimeOffset is invalid or missing", "TimeZone is invalid or missing", "OnapComponent is required", "OnapInstance is required", "OnapName is required", "PolicyName is required and cannot be empty"}
+ inValidErr := []string{"TimeOffset is invalid or missing", "TimeZone is invalid or missing"}
- // Create an invalid OPADecisionRequest
- invalidDecisionRequest := &oapicodegen.OPADecisionRequest{
- CurrentDate: ¤tDate,
- CurrentDateTime: ¤tDateTime,
- CurrentTime: &ctime,
- TimeOffset: &timeOffset,
- TimeZone: &timeZone,
- OnapComponent: nil, // Invalid: should not be nil
- OnapInstance: nil, // Invalid: should not be nil
- OnapName: nil, // Invalid: should not be nil
- PolicyName: "", // Invalid: should not be empty
- PolicyFilter: []string{"user_is_granted"}, // This can remain valid.
- //Input: nil,
- }
- invalidDecisionErrs := []string{"CurrentTime is invalid or missing", "TimeOffset is invalid or missing", "TimeZone is invalid or missing", "OnapComponent is required", "OnapInstance is required", "OnapName is required", "PolicyName is required and cannot be empty"}
+ inValidDecisionErrs := []string{"PolicyName is required and cannot be empty"}
tests := []struct {
name string
request interface{}
expectedErr []string
}{
{"Valid Request", inValidRequest, inValidErr},
- {"Invalid OPADecisionRequest", invalidDecisionRequest, invalidDecisionErrs},
+ {"Invalid OPADecisionRequest", inValidDecisionRequest, inValidDecisionErrs},
}
for _, tt := range tests {
## Curl URL For Deployment.
-1. `curl -u 'policyadmin:zb!XztG34' -X POST -H "Content-Type":"application/yaml" --data-binary @test_resources/policy_deploy_single_policy.yaml http://localhost:30002/policy/api/v1/policytypes/onap.policies.native.opa/versions/1.0.0/policies`
+1. `curl -u 'policyadmin:zb!XztG34' -X POST -H "Content-Type":"application/yaml" --data-binary @toscapolicies/role/policy_role.yaml http://localhost:30002/policy/api/v1/policytypes/onap.policies.native.opa/versions/1.0.0/policies`
-2. `curl -u 'policyadmin:zb!XztG34' -X POST -H "Content-Type":"application/json" -d @test_resources/deploy.json http://localhost:30003/policy/pap/v1/pdps/policies`
+2. `curl -u 'policyadmin:zb!XztG34' -X POST -H "Content-Type":"application/json" -d @toscapolicies/role/deploy_role.json http://localhost:30003/policy/pap/v1/pdps/policies`
## Curl URL For Undeployment
## Curl URL for Batch Undeployment.
-`curl -v -u 'policyadmin:zb!XztG34' -X POST -H "Content-Type":"application/json" -d @test_resources/undeploy_batch_delete.json http://localhost:30003/policy/pap/v1/pdps/deployments/batch`
+`curl -v -u 'policyadmin:zb!XztG34' -X POST -H "Content-Type":"application/json" -d @{"groups": [{"name": "opaGroup","deploymentSubgroups": [{"pdpType": "opa","action": "DELETE","policies": [{"name": "role","version": "2.0.2"}]}]}]} http://localhost:30003/policy/pap/v1/pdps/deployments/batch`
## Decision API Response
## Output For Policy: access_method with empty filter
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": "08:26:41.857Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2025-01-17T08:26:41.857Z", "policyFilter" : [""], "policyName":"access_method","input":{"method":"POST","path":["users"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-{"output":null,"policyName":"access_method","statusMessage":"Policy Filter(s) not matching, Valid Filter(s) are: [allow]"}
+{"output":{"allow":true},"policyName":"access_method"}
## Output For Policy: access_method with filter allow
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": "08:26:41.857Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2025-01-17T08:26:41.857Z", "policyFilter" : ["allow"], "policyName":"access_method","input":{"method":"POST","path":["users"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+
{"output":{"allow":true},"policyName":"access_method"}
## Output For Policy: role with filter allow
{"output":{"allow":true},"policyName":"role"}
+
## Output For policy: role 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": "08:26:41.857Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2025-01-17T08:26:41.857Z", "policyName":"role", "policyFilter": [""], "input":{"user":"alice","action":"write","object":"id123","type":"dog"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+
+{"output":{"allow":true,"user_is_admin":true,"user_is_granted":[]},"policyName":"role"}
+
+## Output For policy: role with filter not matching the allowable filters
+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": "08:26:41.857Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2025-01-17T08:26:41.857Z", "policyName":"role", "policyFilter": ["abc"], "input":{"user":"alice","action":"write","object":"id123","type":"dog"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+
{"output":null,"policyName":"role","statusMessage":"Policy Filter(s) not matching, Valid Filter(s) are: [allow, user_is_admin, user_is_granted]"}
## Output For Policy: blacklist with filter module_allow
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": "08:26:41.857Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2025-01-17T08:26:41.857Z", "policyFilter" : ["module_allow"], "policyName":"blacklist","input":{"vfmodule":["the-vfmodule-where-root-is-true","another-vfmodule-where-root-is-true" ] }}' -X POST http://localhost:8282/policy/pdpo/v1/decision
+
{"output":{"module_allow":{"another-vfmodule-where-root-is-true":true,"the-vfmodule-where-root-is-true":true}},"policyName":"blacklist"}
## Output For Policy: blacklist with Empty Filter
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": "08:26:41.857Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2025-01-17T08:26:41.857Z", "policyFilter" : [""], "policyName":"blacklist","input":{"vfmodule":["the-vfmodule-where-root-is-true","another-vfmodule-where-root-is-true" ] }}' -X POST http://localhost:8282/policy/pdpo/v1/decision
-{"output":null,"policyName":"blacklist","statusMessage":"Policy Filter(s) not matching, Valid Filter(s) are: [module_allow, module_allow/another-vfmodule-where-root-is-true, module_allow/the-vfmodule-where-root-is-true]"}
+
+{"output":{"module_allow":{"another-vfmodule-where-root-is-true":true,"the-vfmodule-where-root-is-true":true}},"policyName":"blacklist"}
## Output For Policy: monitor with filter result
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": "08:26:41.857Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2025-01-17T08:26:41.857Z", "policyFilter" : ["result"], "policyName":"monitor","input":{ "domain": "measurementsForVfScaling", "eventName": "Measurement_vGMUX","controlLoopSchemaType": "VNF","policyScope": "DCAE","policyName": "DCAE.Config_tca-hi-lo","policyVersion": "v0.0.1", "version": "1.0.2","controlname": "ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e","thresholdValue": 0}}' -X POST http://localhost:8282/policy/pdpo/v1/decision
+
{"output":{"result":[{"closedLoopEventStatus":"ABATED","severity":"MAJOR"}]},"policyName":"monitor"}
## Output For Policy: monitor with empty filter
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": "08:26:41.857Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2025-01-17T08:26:41.857Z", "policyFilter" : [""], "policyName":"monitor","input":{ "domain": "measurementsForVfScaling", "eventName": "Measurement_vGMUX","controlLoopSchemaType": "VNF","policyScope": "DCAE","policyName": "DCAE.Config_tca-hi-lo","policyVersion": "v0.0.1", "version": "1.0.2","controlname": "ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e","thresholdValue": 0}}' -X POST http://localhost:8282/policy/pdpo/v1/decision
-{"output":null,"policyName":"monitor","statusMessage":"Policy Filter(s) not matching, Valid Filter(s) are: [result]"}
+
+{"output":{"result":[{"closedLoopEventStatus":"ABATED","severity":"MAJOR"}]},"policyName":"monitor
## 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/statistics
-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,"decisionFailureCount":0,"decisionSuccessCount":0,"deployFailureCount":0,"deploySuccessCount":0, "totalErrorCount":0,"totalPoliciesCount":0,"totalPolicyTypesCount":1,"undeployFailureCount":0,"undeploySuccessCount":0}