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
dataHandler := http.HandlerFunc(data.DataHandler)
http.Handle("/policy/pdpo/v1/data/", basicAuth(dataHandler))
+ http.Handle("/policy/pdpo/v1/data", basicAuth(dataHandler))
+
}
// handles authentication
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)
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)
+ }
}
}
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)
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)
}
}
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 {
OpaDecision(res, req)
assert.Equal(t, http.StatusOK, res.Code)
- assert.NotEmpty(t, res.Body.String())
}
// 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 {
}
}
-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
//Mocking the CreateBundle
err := verifyPolicyByBundleCreation(policy)
- assert.Error(t, err)
+ assert.NoError(t, err)
}
{
Properties: model.PolicyProperties{
Data: map[string]string{
- "node.role": "ewogICAgInVzZXJfcm9sZXMiOiB7CiAgICAgICAgImFsaWNlIjogWwogICAgICAgICAgICAiYWRtaW4iCiAgICAgICAgXSwKICAgICAgICAiYm9iIjogWwogICAgICAgICAgICAiZW1wbG95ZWUiLAogICAgICAgICAgICAiYmlsbGluZyIKICAgICAgICBdLAogICAgICAgICJldmUiOiBbCiAgICAgICAgICAgICJjdXN0b21lciIKICAgICAgICBdCiAgICB9LAogICAgInJvbGVfZ3JhbnRzIjogewogICAgICAgICJjdXN0b21lciI6IFsKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJyZWFkIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImRvZyIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJyZWFkIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImNhdCIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJhZG9wdCIsCiAgICAgICAgICAgICAgICAidHlwZSI6ICJkb2ciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAiYWRvcHQiLAogICAgICAgICAgICAgICAgInR5cGUiOiAiY2F0IgogICAgICAgICAgICB9CiAgICAgICAgXSwKICAgICAgICAiZW1wbG95ZWUiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAicmVhZCIsCiAgICAgICAgICAgICAgICAidHlwZSI6ICJkb2ciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAicmVhZCIsCiAgICAgICAgICAgICAgICAidHlwZSI6ICJjYXQiCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAidXBkYXRlIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImRvZyIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJ1cGRhdGUiLAogICAgICAgICAgICAgICAgInR5cGUiOiAiY2F0IgogICAgICAgICAgICB9CiAgICAgICAgXSwKICAgICAgICAiYmlsbGluZyI6IFsKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJyZWFkIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImZpbmFuY2UiCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAidXBkYXRlIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImZpbmFuY2UiCiAgICAgICAgICAgIH0KICAgICAgICBdCiAgICB9Cn0K",
+ "node.role": "ewogICAgInVzZXJfcm9sZXMiOiB7CiAgICAgICAgImFsaWNlIjogWwogICAgICAgICAgICAiYWRtaW4iCiAgICAgICAgXSwKICAgICAgICAiYm9iIjogWwogICAgICAgICAgICAiZW1wbG95ZWUiLAogICAgICAgICAgICAiYmlsbGluZyIKICAgICAgICBdLAogICAgICAgICJldmUiOiBbCiAgICAgICAgICAgICJjdXN0b21lciIKICAgICAgICBdCiAgICB9LAogICAgInJvbGVfZ3JhbnRzIjogewogICAgICAgICJjdXN0b21lciI6IFsKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJyZWFkIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImRvZyIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJyZWFkIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImNhdCIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJhZG9wdCIsCiAgICAgICAgICAgICAgICAidHlwZSI6ICJkb2ciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAiYWRvcHQiLAogICAgICAgICAgICAgICAgInR5cGUiOiAiY2F0IgogICAgICAgICAgICB9CiAgICAgICAgXSwKICAgICAgICAiZW1wbG95ZWUiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAicmVhZCIsCiAgICAgICAgICAgICAgICAidHlwZSI6ICJkb2ciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAicmVhZCIsCiAgICAgICAgICAgICAgICAidHlwZSI6ICJjYXQiCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAidXBkYXRlIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImRvZyIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJ1cGRhdGUiLAogICAgICAgICAgICAgICAgInR5cGUiOiAiY2F0IgogICAgICAgICAgICB9CiAgICAgICAgXSwKICAgICAgICAiYmlsbGluZyI6IFsKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJyZWFkIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImZpbmFuY2UiCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAidXBkYXRlIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImZpbmFuY2UiCiAgICAgICAgICAgIH0KICAgICAgICBdCiAgICB9Cn0K",
},
Policy: map[string]string{
"role": "ewogICAgInVzZXJfcm9sZXMiOiB7CiAgICAgICAgImFsaWNlIjogWwogICAgICAgICAgICAiYWRtaW4iCiAgICAgICAgXSwKICAgICAgICAiYm9iIjogWwogICAgICAgICAgICAiZW1wbG95ZWUiLAogICAgICAgICAgICAiYmlsbGluZyIKICAgICAgICBdLAogICAgICAgICJldmUiOiBbCiAgICAgICAgICAgICJjdXN0b21lciIKICAgICAgICBdCiAgICB9LAogICAgInJvbGVfZ3JhbnRzIjogewogICAgICAgICJjdXN0b21lciI6IFsKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJyZWFkIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImRvZyIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJyZWFkIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImNhdCIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJhZG9wdCIsCiAgICAgICAgICAgICAgICAidHlwZSI6ICJkb2ciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAiYWRvcHQiLAogICAgICAgICAgICAgICAgInR5cGUiOiAiY2F0IgogICAgICAgICAgICB9CiAgICAgICAgXSwKICAgICAgICAiZW1wbG95ZWUiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAicmVhZCIsCiAgICAgICAgICAgICAgICAidHlwZSI6ICJkb2ciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAicmVhZCIsCiAgICAgICAgICAgICAgICAidHlwZSI6ICJjYXQiCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAidXBkYXRlIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImRvZyIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJ1cGRhdGUiLAogICAgICAgICAgICAgICAgInR5cGUiOiAiY2F0IgogICAgICAgICAgICB9CiAgICAgICAgXSwKICAgICAgICAiYmlsbGluZyI6IFsKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImFjdGlvbiI6ICJyZWFkIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImZpbmFuY2UiCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJhY3Rpb24iOiAidXBkYXRlIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImZpbmFuY2UiCiAgICAgICAgICAgIH0KICAgICAgICBdCiAgICB9Cn0K",
)
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
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
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
// 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"`
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"`
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
+}
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
}
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)
}
}
}
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()
_, 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)
}
_, 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