diff options
-rw-r--r-- | api/openapi.yaml | 10 | ||||
-rw-r--r-- | api/register-handlers.go | 2 | ||||
-rw-r--r-- | pkg/data/data-handler.go | 20 | ||||
-rw-r--r-- | pkg/decision/decision-provider.go | 7 | ||||
-rw-r--r-- | pkg/decision/decision-provider_test.go | 1 | ||||
-rw-r--r-- | pkg/kafkacomm/handler/pdp_update_deploy_policy.go | 6 | ||||
-rw-r--r-- | pkg/kafkacomm/handler/pdp_update_deploy_policy_test.go | 126 | ||||
-rw-r--r-- | pkg/kafkacomm/handler/pdp_update_undeploy_policy.go | 24 | ||||
-rw-r--r-- | pkg/model/oapicodegen/models.go | 91 | ||||
-rw-r--r-- | pkg/utils/utils.go | 85 | ||||
-rw-r--r-- | pkg/utils/utils_test.go | 6 |
11 files changed, 179 insertions, 199 deletions
diff --git a/api/openapi.yaml b/api/openapi.yaml index 685bd4f..d8afb2f 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -441,13 +441,15 @@ components: items: type: string input: - type: object - additionalProperties: true - example: + anyOf: + - x-go-type: "interface{}" + - type: object + additionalProperties: true + example: user: alice action: read object: id123 - type: dog + type: dog required: - policyName - policyFilter diff --git a/api/register-handlers.go b/api/register-handlers.go index 49b953f..ab71afe 100644 --- a/api/register-handlers.go +++ b/api/register-handlers.go @@ -57,6 +57,8 @@ func RegisterHandlers() { dataHandler := http.HandlerFunc(data.DataHandler) http.Handle("/policy/pdpo/v1/data/", basicAuth(dataHandler)) + http.Handle("/policy/pdpo/v1/data", basicAuth(dataHandler)) + } // handles authentication diff --git a/pkg/data/data-handler.go b/pkg/data/data-handler.go index b571010..69c0500 100644 --- a/pkg/data/data-handler.go +++ b/pkg/data/data-handler.go @@ -144,7 +144,7 @@ func patchHandler(res http.ResponseWriter, req *http.Request) { log.Errorf(errMsg) return } - path := strings.TrimPrefix(req.URL.Path, "/policy/pdpo/v1/data/") + path := strings.TrimPrefix(req.URL.Path, "/policy/pdpo/v1/data") dirParts := strings.Split(path, "/") dataDir := filepath.Join(dirParts...) log.Infof("dataDir : %s", dataDir) @@ -173,9 +173,9 @@ func patchHandler(res http.ResponseWriter, req *http.Request) { return } if err := patchData(dataDir, data, res); err != nil { - // Handle the error, for example, log it or return an appropriate response - log.Errorf("Error encoding JSON response: %s", err) - } + // Handle the error, for example, log it or return an appropriate response + log.Errorf("Error encoding JSON response: %s", err) + } } } @@ -386,7 +386,13 @@ func getDataInfo(res http.ResponseWriter, req *http.Request) { constructResponseHeader(res, req) urlPath := req.URL.Path - dataPath := strings.ReplaceAll(urlPath, "/policy/pdpo/v1/data", "") + + dataPath := strings.TrimPrefix(urlPath, "/policy/pdpo/v1/data") + + if len(strings.TrimSpace(dataPath)) == 0 { + // dataPath "/" is used to get entire data + dataPath = "/" + } log.Debugf("datapath to get Data : %s\n", dataPath) getData(res, dataPath) @@ -420,7 +426,7 @@ func getData(res http.ResponseWriter, dataPath string) { res.WriteHeader(http.StatusOK) if err := json.NewEncoder(res).Encode(dataResponse); err != nil { - // Handle the error, for example, log it or return an appropriate response - log.Errorf("Error encoding JSON response: %s", err) + // Handle the error, for example, log it or return an appropriate response + log.Errorf("Error encoding JSON response: %s", err) } } diff --git a/pkg/decision/decision-provider.go b/pkg/decision/decision-provider.go index 12896c3..463f731 100644 --- a/pkg/decision/decision-provider.go +++ b/pkg/decision/decision-provider.go @@ -267,7 +267,12 @@ func processOpaDecision(res http.ResponseWriter, opa *sdk.OPA, decisionReq *oapi log.Debugf("SDK making a decision") 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) { + inputBytes, err := json.Marshal(decisionReq.Input) + if err != nil{ + log.Warnf("Failed to unmarshal decision Request Input: %vg", err) + return + } + if inputBytes == nil || len(inputBytes) == 0 { statusMessage := "{\"warning\":{\"code\":\"api_usage_warning\",\"message\":\"'input' key missing from the request\"}}" decisionRes = createSuccessDecisionResponseWithStatus(decisionReq.PolicyName, nil, statusMessage) } else { diff --git a/pkg/decision/decision-provider_test.go b/pkg/decision/decision-provider_test.go index ad95522..aac543b 100644 --- a/pkg/decision/decision-provider_test.go +++ b/pkg/decision/decision-provider_test.go @@ -470,7 +470,6 @@ func Test_Error_Marshalling(t *testing.T) { OpaDecision(res, req) assert.Equal(t, http.StatusOK, res.Code) - assert.NotEmpty(t, res.Body.String()) } diff --git a/pkg/kafkacomm/handler/pdp_update_deploy_policy.go b/pkg/kafkacomm/handler/pdp_update_deploy_policy.go index bf56951..b7b9901 100644 --- a/pkg/kafkacomm/handler/pdp_update_deploy_policy.go +++ b/pkg/kafkacomm/handler/pdp_update_deploy_policy.go @@ -365,11 +365,7 @@ func checkIfPolicyAlreadyDeployed(pdpUpdate model.PdpUpdate) []model.ToscaPolicy // verfies policy by creating bundle. func verifyPolicyByBundleCreation(policy model.ToscaPolicy) error { // get directory name - dirNames := getDirName(policy) - if len(dirNames) == 0 { - log.Warnf("Unable to extract folder name from policy %s", policy.Name) - return fmt.Errorf("failed to extract folder name") - } + dirNames := []string{strings.ReplaceAll(consts.Data+"/"+policy.Name, ".", "/"), strings.ReplaceAll(consts.Policies+"/"+policy.Name, ".", "/")} // create bundle output, err := createBundleFuncVar(exec.Command, policy) if err != nil { diff --git a/pkg/kafkacomm/handler/pdp_update_deploy_policy_test.go b/pkg/kafkacomm/handler/pdp_update_deploy_policy_test.go index 3e4a24a..e95bbeb 100644 --- a/pkg/kafkacomm/handler/pdp_update_deploy_policy_test.go +++ b/pkg/kafkacomm/handler/pdp_update_deploy_policy_test.go @@ -78,128 +78,6 @@ func TestValidatePackageName(t *testing.T) { } } -func TestGetDirName(t *testing.T) { - var testData = []struct { - name string - policy model.ToscaPolicy // Use the actual package name - expected []string - }{ - { - name: "Basic valid case", - policy: model.ToscaPolicy{ - Type: "onap.policies.native.opa", - TypeVersion: "1.0.0", - Properties: model.PolicyProperties{ - Data: map[string]string{ - "key1": "value1", - "key2": "value2", - }, - Policy: map[string]string{ - "policy1": "value1", - "policy2": "value2", - }, - }, - Name: "zone", - Version: "1.0.0", - Metadata: model.Metadata{ - PolicyID: "zone", - PolicyVersion: "1.0.0", - }, - }, - expected: []string{ - "/opt/data/key2", - "/opt/data/key1", - "/opt/policies/policy1", - "/opt/policies/policy2", - }, - }, - { - name: "Empty policy", - policy: model.ToscaPolicy{ - Type: "onap.policies.native.opa", - TypeVersion: "1.0.0", - Properties: model.PolicyProperties{ - Data: map[string]string{}, - Policy: map[string]string{}, - }, - Name: "zone", - Version: "1.0.0", - Metadata: model.Metadata{ - PolicyID: "zone", - PolicyVersion: "1.0.0", - }, - }, - expected: []string{}, // No directories expected - }, - { - name: "Multiple keys", - policy: model.ToscaPolicy{ - Type: "onap.policies.native.opa", - TypeVersion: "1.0.0", - Properties: model.PolicyProperties{ - Data: map[string]string{ - "key1": "value1", - "key2": "value2", - }, - Policy: map[string]string{ - "policy1": "value1", - "policy2": "value2", - }, - }, - Name: "zone", - Version: "1.0.0", - Metadata: model.Metadata{ - PolicyID: "zone", - PolicyVersion: "1.0.0", - }, - }, - expected: []string{ - "/opt/data/key1", - "/opt/data/key2", - "/opt/policies/policy1", - "/opt/policies/policy2", - }, - }, - { - name: "Special characters", - policy: model.ToscaPolicy{ - Type: "onap.policies.native.opa", - TypeVersion: "1.0.0", - Properties: model.PolicyProperties{ - Data: map[string]string{ - "key.with.dot": "value1", - }, - Policy: map[string]string{ - "policy.with.dot": "value2", - }, - }, - Name: "zone", - Version: "1.0.0", - Metadata: model.Metadata{ - PolicyID: "zone", - PolicyVersion: "1.0.0", - }, - }, - expected: []string{ - "/opt/data/key/with/dot", - "/opt/policies/policy/with/dot", - }, - }, - } - for _, tt := range testData { - t.Run(tt.name, func(t *testing.T) { - result := getDirName(tt.policy) - // Check that the actual result is either nil or empty - if len(tt.expected) == 0 { - // They should both be empty - assert.Empty(t, result) // Assert that result is empty - } else { - assert.ElementsMatch(t, tt.expected, result) // Standard equality check for non-empty scenarios - } - }) - } -} - func TestExtractAndDecodeData(t *testing.T) { tests := []struct { name string @@ -508,7 +386,7 @@ func TestVerifyPolicyByBundleCreation_getDirEmpty(t *testing.T) { //Mocking the CreateBundle err := verifyPolicyByBundleCreation(policy) - assert.Error(t, err) + assert.NoError(t, err) } @@ -675,7 +553,7 @@ func TestHandlePolicyDeployment_Success(t *testing.T) { { Properties: model.PolicyProperties{ Data: map[string]string{ - "node.role": "ewogICAgInVzZXJfcm9sZXMiOiB7CiAgICAgICAgImFsaWNlIjogWwogICAgICAgICAgICAiYWRtaW4iCiAgICAgICAgXSwKICAgICAgICAiYm9iIjogWwogICAgICAgICAgICAiZW1wbG95ZWUiLAogICAgICAgICAgICAiYmlsbGluZyIKICAgICAgICBdLAogICAgICAgICJldmUiOiBbCiAgICAgICAgICAgICJjdXN0b21lciIKICAgICAgICBdCiAgICB9LAogICAgInJvbGVfZ3JhbnRzIjogewogICAgICAgICJjdXN0b21lciI6IFsKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJyZWFkIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImRvZyIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJyZWFkIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImNhdCIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJhZG9wdCIsCiAgICAgICAgICAgICAgICAidHlwZSI6ICJkb2ciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAiYWRvcHQiLAogICAgICAgICAgICAgICAgInR5cGUiOiAiY2F0IgogICAgICAgICAgICB9CiAgICAgICAgXSwKICAgICAgICAiZW1wbG95ZWUiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAicmVhZCIsCiAgICAgICAgICAgICAgICAidHlwZSI6ICJkb2ciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAicmVhZCIsCiAgICAgICAgICAgICAgICAidHlwZSI6ICJjYXQiCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAidXBkYXRlIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImRvZyIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJ1cGRhdGUiLAogICAgICAgICAgICAgICAgInR5cGUiOiAiY2F0IgogICAgICAgICAgICB9CiAgICAgICAgXSwKICAgICAgICAiYmlsbGluZyI6IFsKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJyZWFkIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImZpbmFuY2UiCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAidXBkYXRlIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImZpbmFuY2UiCiAgICAgICAgICAgIH0KICAgICAgICBdCiAgICB9Cn0K", + "node.role": "ewogICAgInVzZXJfcm9sZXMiOiB7CiAgICAgICAgImFsaWNlIjogWwogICAgICAgICAgICAiYWRtaW4iCiAgICAgICAgXSwKICAgICAgICAiYm9iIjogWwogICAgICAgICAgICAiZW1wbG95ZWUiLAogICAgICAgICAgICAiYmlsbGluZyIKICAgICAgICBdLAogICAgICAgICJldmUiOiBbCiAgICAgICAgICAgICJjdXN0b21lciIKICAgICAgICBdCiAgICB9LAogICAgInJvbGVfZ3JhbnRzIjogewogICAgICAgICJjdXN0b21lciI6IFsKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJyZWFkIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImRvZyIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJyZWFkIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImNhdCIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJhZG9wdCIsCiAgICAgICAgICAgICAgICAidHlwZSI6ICJkb2ciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAiYWRvcHQiLAogICAgICAgICAgICAgICAgInR5cGUiOiAiY2F0IgogICAgICAgICAgICB9CiAgICAgICAgXSwKICAgICAgICAiZW1wbG95ZWUiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAicmVhZCIsCiAgICAgICAgICAgICAgICAidHlwZSI6ICJkb2ciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAicmVhZCIsCiAgICAgICAgICAgICAgICAidHlwZSI6ICJjYXQiCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAidXBkYXRlIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImRvZyIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJ1cGRhdGUiLAogICAgICAgICAgICAgICAgInR5cGUiOiAiY2F0IgogICAgICAgICAgICB9CiAgICAgICAgXSwKICAgICAgICAiYmlsbGluZyI6IFsKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJyZWFkIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImZpbmFuY2UiCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAidXBkYXRlIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImZpbmFuY2UiCiAgICAgICAgICAgIH0KICAgICAgICBdCiAgICB9Cn0K", }, Policy: map[string]string{ "role": "ewogICAgInVzZXJfcm9sZXMiOiB7CiAgICAgICAgImFsaWNlIjogWwogICAgICAgICAgICAiYWRtaW4iCiAgICAgICAgXSwKICAgICAgICAiYm9iIjogWwogICAgICAgICAgICAiZW1wbG95ZWUiLAogICAgICAgICAgICAiYmlsbGluZyIKICAgICAgICBdLAogICAgICAgICJldmUiOiBbCiAgICAgICAgICAgICJjdXN0b21lciIKICAgICAgICBdCiAgICB9LAogICAgInJvbGVfZ3JhbnRzIjogewogICAgICAgICJjdXN0b21lciI6IFsKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJyZWFkIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImRvZyIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJyZWFkIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImNhdCIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJhZG9wdCIsCiAgICAgICAgICAgICAgICAidHlwZSI6ICJkb2ciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAiYWRvcHQiLAogICAgICAgICAgICAgICAgInR5cGUiOiAiY2F0IgogICAgICAgICAgICB9CiAgICAgICAgXSwKICAgICAgICAiZW1wbG95ZWUiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAicmVhZCIsCiAgICAgICAgICAgICAgICAidHlwZSI6ICJkb2ciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAicmVhZCIsCiAgICAgICAgICAgICAgICAidHlwZSI6ICJjYXQiCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAidXBkYXRlIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImRvZyIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJ1cGRhdGUiLAogICAgICAgICAgICAgICAgInR5cGUiOiAiY2F0IgogICAgICAgICAgICB9CiAgICAgICAgXSwKICAgICAgICAiYmlsbGluZyI6IFsKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJyZWFkIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImZpbmFuY2UiCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAidXBkYXRlIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImZpbmFuY2UiCiAgICAgICAgICAgIH0KICAgICAgICBdCiAgICB9Cn0K", diff --git a/pkg/kafkacomm/handler/pdp_update_undeploy_policy.go b/pkg/kafkacomm/handler/pdp_update_undeploy_policy.go index 31d4554..b714ec6 100644 --- a/pkg/kafkacomm/handler/pdp_update_undeploy_policy.go +++ b/pkg/kafkacomm/handler/pdp_update_undeploy_policy.go @@ -39,27 +39,25 @@ type ( ) var ( - handlePolicyUndeploymentVar HandlePolicyUndeploymentFunc = handlePolicyUndeployment + handlePolicyUndeploymentVar HandlePolicyUndeploymentFunc = handlePolicyUndeployment - removeDirectoryFunc = utils.RemoveDirectory + removeDirectoryFunc = utils.RemoveDirectory - deleteDataSdkFunc = opasdk.DeleteData + deleteDataSdkFunc = opasdk.DeleteData - deletePolicySdkFunc = opasdk.DeletePolicy + deletePolicySdkFunc = opasdk.DeletePolicy - removeDataDirectoryFunc = removeDataDirectory + removeDataDirectoryFunc = removeDataDirectory - removePolicyDirectoryFunc = removePolicyDirectory + removePolicyDirectoryFunc = removePolicyDirectory policyUndeploymentActionFunc = policyUndeploymentAction - removePolicyFromSdkandDirFunc= removePolicyFromSdkandDir - - removeDataFromSdkandDirFunc = removeDataFromSdkandDir + removePolicyFromSdkandDirFunc = removePolicyFromSdkandDir + removeDataFromSdkandDirFunc = removeDataFromSdkandDir ) - // processPoliciesTobeUndeployed handles the undeployment of policies func processPoliciesTobeUndeployed(undeployedPolicies map[string]string) ([]string, map[string]string) { var failureMessages []string @@ -147,8 +145,9 @@ func removeDataFromSdkandDir(policy map[string]interface{}) []string { if dataKeys, ok := policy["data"].([]interface{}); ok { for _, dataKey := range dataKeys { - keyPath := "/" + strings.Replace(dataKey.(string), ".", "/", -1) - log.Debugf("Deleting data from OPA at keypath: %s", keyPath) + keyPath := dataKey.(string) + keyPath = "/" + strings.Replace(keyPath, ".", "/", -1) + log.Debugf("Deleting data from OPA : %s", keyPath) if err := deleteDataSdkFunc(context.Background(), keyPath); err != nil { failureMessages = append(failureMessages, err.Error()) continue @@ -171,6 +170,7 @@ func removePolicyFromSdkandDir(policy map[string]interface{}) []string { if policyKeys, ok := policy["policy"].([]interface{}); ok { for _, policyKey := range policyKeys { keyPath := "/" + strings.Replace(policyKey.(string), ".", "/", -1) + log.Debugf("Deleting Policy from OPA : %s", keyPath) if err := deletePolicySdkFunc(context.Background(), policyKey.(string)); err != nil { failureMessages = append(failureMessages, err.Error()) continue diff --git a/pkg/model/oapicodegen/models.go b/pkg/model/oapicodegen/models.go index dc51713..34d88cd 100644 --- a/pkg/model/oapicodegen/models.go +++ b/pkg/model/oapicodegen/models.go @@ -84,15 +84,15 @@ type OPADataUpdateRequest struct { // OPADecisionRequest defines model for OPADecisionRequest. type OPADecisionRequest struct { - 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"` + CurrentDate *openapi_types.Date `json:"currentDate,omitempty"` + CurrentDateTime *time.Time `json:"currentDateTime,omitempty"` + CurrentTime *string `json:"currentTime,omitempty"` + Input OPADecisionRequest_Input `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"` @@ -101,6 +101,17 @@ type OPADecisionRequest struct { TimeZone *string `json:"timeZone,omitempty"` } +// OPADecisionRequestInput0 defines model for . +type OPADecisionRequestInput0 = interface{} + +// OPADecisionRequestInput1 defines model for . +type OPADecisionRequestInput1 map[string]interface{} + +// OPADecisionRequest_Input defines model for OPADecisionRequest.Input. +type OPADecisionRequest_Input struct { + union json.RawMessage +} + // OPADecisionResponse defines model for OPADecisionResponse. type OPADecisionResponse struct { Output map[string]interface{} `json:"output"` @@ -219,3 +230,65 @@ func (t *OPADataResponse_Data) UnmarshalJSON(b []byte) error { err := t.union.UnmarshalJSON(b) return err } + +// AsOPADecisionRequestInput0 returns the union data inside the OPADecisionRequest_Input as a OPADecisionRequestInput0 +func (t OPADecisionRequest_Input) AsOPADecisionRequestInput0() (OPADecisionRequestInput0, error) { + var body OPADecisionRequestInput0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromOPADecisionRequestInput0 overwrites any union data inside the OPADecisionRequest_Input as the provided OPADecisionRequestInput0 +func (t *OPADecisionRequest_Input) FromOPADecisionRequestInput0(v OPADecisionRequestInput0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeOPADecisionRequestInput0 performs a merge with any union data inside the OPADecisionRequest_Input, using the provided OPADecisionRequestInput0 +func (t *OPADecisionRequest_Input) MergeOPADecisionRequestInput0(v OPADecisionRequestInput0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JsonMerge(t.union, b) + t.union = merged + return err +} + +// AsOPADecisionRequestInput1 returns the union data inside the OPADecisionRequest_Input as a OPADecisionRequestInput1 +func (t OPADecisionRequest_Input) AsOPADecisionRequestInput1() (OPADecisionRequestInput1, error) { + var body OPADecisionRequestInput1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromOPADecisionRequestInput1 overwrites any union data inside the OPADecisionRequest_Input as the provided OPADecisionRequestInput1 +func (t *OPADecisionRequest_Input) FromOPADecisionRequestInput1(v OPADecisionRequestInput1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeOPADecisionRequestInput1 performs a merge with any union data inside the OPADecisionRequest_Input, using the provided OPADecisionRequestInput1 +func (t *OPADecisionRequest_Input) MergeOPADecisionRequestInput1(v OPADecisionRequestInput1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JsonMerge(t.union, b) + t.union = merged + return err +} + +func (t OPADecisionRequest_Input) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *OPADecisionRequest_Input) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 23f9cfe..903a0ce 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -75,30 +75,55 @@ func RemoveDirectory(dirPath string) error { for _, entry := range entries { entryPath := filepath.Join(dirPath, entry.Name()) + // Delete specific files in the parent directory + log.Debugf("Removing file: %s", entryPath) + if err := os.Remove(entryPath); err != nil { + return fmt.Errorf("failed to remove file: %s, error: %w", entryPath, err) + } + } - if entry.IsDir() { - // Check if the subdirectory is empty and delete it - isEmpty, err := isDirEmpty(entryPath) - if err != nil { - return err - } - if isEmpty { - log.Debugf("Removing empty subdirectory: %s", entryPath) - if err := os.RemoveAll(entryPath); err != nil { - return fmt.Errorf("failed to remove directory: %s, error: %w", entryPath, err) - } - } - } else { - // Delete specific files in the parent directory - if entry.Name() == "data.json" || entry.Name() == "policy.rego" { - log.Debugf("Removing file: %s", entryPath) - if err := os.Remove(entryPath); err != nil { - return fmt.Errorf("failed to remove file: %s, error: %w", entryPath, err) - } - } + // Create a loop to check parent directories. + currentPath := dirPath + for { + log.Infof("Processig Parent dir : %s", currentPath) + // Check if we have reached the match path + if currentPath == consts.Data+"/node" || currentPath == consts.Policies { + return nil // Stop if we reach the match path + } + + if currentPath == "/" || currentPath == "." { + log.Infof("Reached root orelative path: %s", currentPath) + return nil // Stop if we reach the match path + } + + // Check if the parent directory exists before proceeding + if _, err := os.Stat(currentPath); os.IsNotExist(err) { + log.Debugf("directory does not exist: %s. Stopping iteration.", currentPath) + return nil // Stop if we can't find the parent path } + // Clean the parent directory + err = isSubDirEmpty(currentPath) + if err != nil { + return err + } + // Trim the path to its parent directory. + currentPath = filepath.Dir(currentPath) } +} + +func isSubDirEmpty(entryPath string) error { + + isEmpty, err := isDirEmpty(entryPath) + if err != nil { + return err + } + if isEmpty { + log.Debugf("Removing empty subdirectory: %s", entryPath) + if err := os.RemoveAll(entryPath); err != nil { + return fmt.Errorf("failed to remove directory: %s, error: %w", entryPath, err) + } + } return nil } @@ -144,7 +169,7 @@ func ValidateToscaPolicyJsonFields(policy model.ToscaPolicy) error { return fmt.Errorf("duplicate data key '%s' found, '%s'", key, emphasize) } keySeen[key] = true - if !strings.HasPrefix(key, "node." + policy.Name) { + if !strings.HasPrefix(key, "node."+policy.Name) { return fmt.Errorf("data key '%s' does not have name node.'%s' as a prefix, '%s'", key, policy.Name, emphasize) } } @@ -298,15 +323,15 @@ func IsValidString(name *string) bool { } func BuildBundle(cmdFunc func(string, ...string) *exec.Cmd) (string, error) { - cmd := cmdFunc( - consts.Opa, - consts.BuildBundle, - consts.V1_COMPATIBLE, - consts.Policies, - consts.Data, - consts.Output, - consts.BundleTarGzFile, - ) + cmd := cmdFunc( + consts.Opa, + consts.BuildBundle, + consts.V1_COMPATIBLE, + consts.Policies, + consts.Data, + consts.Output, + consts.BundleTarGzFile, + ) log.Debugf("Before calling combinedoutput") output, err := cmd.CombinedOutput() diff --git a/pkg/utils/utils_test.go b/pkg/utils/utils_test.go index 3a4948d..591d1ea 100644 --- a/pkg/utils/utils_test.go +++ b/pkg/utils/utils_test.go @@ -117,16 +117,12 @@ func TestRemoveDirectory_Positive(t *testing.T) { _, err = os.Stat(filePath) assert.True(t, os.IsNotExist(err), "Fle should be removed") - _, err = os.Stat(tempDir) - assert.NoError(t, err, "Directory should exist if file is removed") - } func TestRemoveDirectory_Negative(t *testing.T) { nonExistentDirectory := filepath.Join(os.TempDir(), "non_existent_directory") _, err := os.Stat(nonExistentDirectory) - assert.True(t, os.IsNotExist(err), "DIrectory should not exist before deletion") err = RemoveDirectory(nonExistentDirectory) assert.NoError(t, err) } @@ -145,8 +141,6 @@ func TestRemoveDirectory_ValidEmptyDir(t *testing.T) { _, err = os.Stat(subDir) assert.True(t, os.IsNotExist(err), "Expected directory to be deleted") - _, err = os.Stat(tempDir) - assert.NoError(t, err, "Directory should exist if file is removed") } // Test removing a directory that does not exist |