Skip to content

Commit

Permalink
feat(resource-groups): add support for OCI (#1410)
Browse files Browse the repository at this point in the history
CAD-416
  • Loading branch information
hazedav authored Oct 13, 2023
1 parent 72b67b2 commit 7603370
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 5 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ integration-only: install-tools ## Run integration tests
team_member \
vulnerability \
report_definitions \
component" -run=$(regex)
component \
resource_groups" -run=$(regex)

.PHONY: integration-lql
integration-lql: build-cli-cross-platform integration-lql-only ## Build and run lql integration tests
Expand Down
3 changes: 3 additions & 0 deletions api/resource_groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ const (

// requires Org Access account client.WithOrgAccess()
LwAccountResourceGroup

OciResourceGroup
)

// ResourceGroupTypes is the list of available Resource Group types
Expand All @@ -76,6 +78,7 @@ var ResourceGroupTypes = map[ResourceGroupType]string{
GcpResourceGroup: "GCP",
LwAccountResourceGroup: "LW_ACCOUNT",
MachineResourceGroup: "MACHINE",
OciResourceGroup: "OCI",
}

// String returns the string representation of a Resource Group type
Expand Down
2 changes: 1 addition & 1 deletion api/resource_groups_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
"github.com/pkg/errors"
)

func (svc *ResourceGroupsV2Service) List() (response ResourceGroupsResponse, err error) {
func (svc *ResourceGroupsV2Service) List() (response ResourceGroupsV2Response, err error) {
var rawResponse ResourceGroupsV2Response
err = svc.client.RequestDecoder("GET", apiV2ResourceGroups, nil, &rawResponse)
if err != nil {
Expand Down
9 changes: 6 additions & 3 deletions cli/cmd/resource_groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ Then navigate to Settings > Resource Groups.
rows = append(rows, []string{g.Id, g.ResType, g.Name, g.status, IsDefault(g.IsDefault)})
}

cli.OutputHuman(renderSimpleTable([]string{"RESOURCE GUID", "TYPE", "NAME", "STATUS", "DEFAULT"}, rows))
cli.OutputHuman(renderSimpleTable([]string{"RESOURCE GROUP ID", "TYPE", "NAME", "STATUS", "DEFAULT"}, rows))
return nil
},
}
Expand Down Expand Up @@ -178,15 +178,15 @@ Then navigate to Settings > Resource Groups.
groupCommon = append(groupCommon,
[]string{group.Id, group.ResType, group.Name, group.status, IsDefault(group.IsDefault)},
)
cli.OutputHuman(renderSimpleTable([]string{"RESOURCE ID", "TYPE", "NAME", "STATE", "DEFAULT"}, groupCommon))
cli.OutputHuman(renderSimpleTable([]string{"RESOURCE GROUP ID", "TYPE", "NAME", "STATE", "DEFAULT"}, groupCommon))
cli.OutputHuman("\n")
cli.OutputHuman(buildResourceGroupPropsTable(group))
} else {
groupCommon = append(groupCommon,
[]string{group.Id, group.ResType, group.Name, group.Description, group.status,
IsDefault(group.IsDefault), group.UpdatedBy, group.UpdatedTime.UTC().String()},
)
cli.OutputHuman(renderSimpleTable([]string{"RESOURCE ID", "TYPE", "NAME", "DESCRIPTION", "STATE",
cli.OutputHuman(renderSimpleTable([]string{"RESOURCE GROUP ID", "TYPE", "NAME", "DESCRIPTION", "STATE",
"DEFAULT", "UPDATED BY", "UPDATED_TIME"}, groupCommon))
}

Expand Down Expand Up @@ -277,6 +277,7 @@ func promptCreateResourceGroup() error {
"GCP(v2)",
"CONTAINER(v2)",
"MACHINE(v2)",
"OCI(v2)",
)
}

Expand Down Expand Up @@ -315,6 +316,8 @@ func promptCreateResourceGroup() error {
return createResourceGroupV2("CONTAINER")
case "MACHINE(v2)":
return createResourceGroupV2("MACHINE")
case "OCI(v2)":
return createResourceGroupV2("OCI")
default:
return errors.New("unknown resource group type")
}
Expand Down
9 changes: 9 additions & 0 deletions integration/context/ctx.toml
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,15 @@ dirs = ["lwgenerate/"]
]
dirs = []

[resource_groups]
files = [
"resource_group_v2.go",
"resource_groups.go",
"resource_groups_v2.go",
"resource_groups_version_service.go"
]
dirs = []

[team_member]
files = ["team_members.go"]
dirs = []
Expand Down
159 changes: 159 additions & 0 deletions integration/resource_groups_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
//go:build resource_groups

// Author:: Salim Afiune Maya (<afiune@lacework.net>)
// Copyright:: Copyright 2020, Lacework Inc.
// License:: Apache License, Version 2.0
//
// 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.
//

package integration

import (
"encoding/json"
"strings"
"testing"

"github.com/lacework/go-sdk/api"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)

var testResourceGroup string = `{"name":"CLI_TestCreateResourceGroup","resourceType":"AWS","query":{"filters":{"filter0":{"field":"Resource Tag","operation":"INCLUDES","values":["*"],"key":"HOST"},"filter1":{"field":"Region","operation":"STARTS_WITH","values":["ap-south"]}},"expression":{"operator":"AND","children":[{"filterName":"filter0"},{"filterName":"filter1"}]}},"description":"Resource Group Created By CLI Integration Testing","enabled":1}`

func createResourceGroup() (string, error) {
var resourceGroupV2Response api.ResourceGroupV2Response

out, stderr, exitcode := LaceworkCLIWithTOMLConfig(
"api", "post", "v2/ResourceGroups", "-d", testResourceGroup, "--json",
)
if stderr.String() != "" {
return "", errors.New(stderr.String())
}
if exitcode != 0 {
return "", errors.New("non-zero exit code")
}

err := json.Unmarshal(out.Bytes(), &resourceGroupV2Response)
if err != nil {
return "", err
}
return resourceGroupV2Response.Data.ID(), nil
}

func popResourceGroup() (string, error) {
type resourceGroup struct {
Id string `json:"resource_guid"`
}
type listResourceGroupsResponse struct {
ResourceGroups []resourceGroup `json:"resource_groups"`
}

var resourceGroups listResourceGroupsResponse

out, stderr, exitcode := LaceworkCLIWithTOMLConfig(
"resource-group", "list", "--json", "--nocache",
)
if stderr.String() != "" {
return "", errors.New(stderr.String())
}
if exitcode != 0 {
return "", errors.New("non-zero exit code")
}

err := json.Unmarshal(out.Bytes(), &resourceGroups)
if err != nil {
return "", err
}

for _, rg := range resourceGroups.ResourceGroups {
return rg.Id, nil
}
return "", errors.New("no resource groups found")
}

func TestResourceGroupCreateEditor(t *testing.T) {
// create
out, err, exitcode := LaceworkCLIWithTOMLConfig("resource-group", "create")
assert.Contains(t, out.String(), "Choose a resource group type to create")
assert.Contains(t, out.String(), "[Use arrows to move, type to filter]")
assert.Contains(t, err.String(), "ERROR unable to create resource group:")
assert.Equal(t, 1, exitcode, "EXITCODE is not the expected one")
}

func TestResourceGroupList(t *testing.T) {
// list (output human)
out, err, exitcode := LaceworkCLIWithTOMLConfig("resource-group", "list")
assert.Contains(t, out.String(), "RESOURCE GROUP ID")
assert.Contains(t, out.String(), "All Aws Accounts")
assert.Empty(t, err.String(), "STDERR should be empty")
assert.Equal(t, 0, exitcode, "EXITCODE is not the expected one")

// list (output json)
out, err, exitcode = LaceworkCLIWithTOMLConfig("resource-group", "list", "--json")
assert.Contains(t, out.String(), `"resource_guid"`)
assert.Contains(t, out.String(), `"type": "AWS"`)
assert.Empty(t, err.String(), "STDERR should be empty")
assert.Equal(t, 0, exitcode, "EXITCODE is not the expected one")
}

func TestPolicyShowNoInput(t *testing.T) {
out, err, exitcode := LaceworkCLIWithTOMLConfig("resource-group", "show")
assert.Empty(t, out.String(), "STDOUT should be empty")
assert.Contains(t, err.String(), "ERROR accepts 1 arg(s), received 0")
assert.Equal(t, 1, exitcode, "EXITCODE is not the expected one")
}

func TestResourceGroupShow(t *testing.T) {
resourceGroupShowID, err := popResourceGroup()
if err != nil {
assert.FailNow(t, err.Error())
}

t.Run("Human Output", func(t *testing.T) {
out, err, exitcode := LaceworkCLIWithTOMLConfig("resource-group", "show", resourceGroupShowID)
assert.Contains(t, out.String(), "RESOURCE GROUP ID")
assert.Contains(t, out.String(), resourceGroupShowID)
assert.Empty(t, err.String(), "STDERR should be empty")
assert.Equal(t, 0, exitcode, "EXITCODE is not the expected one")
})

t.Run("JSON Output", func(t *testing.T) {
out, err, exitcode := LaceworkCLIWithTOMLConfig("resource-group", "show", resourceGroupShowID, "--json")
assert.Contains(t, out.String(), `"resource_guid"`)
assert.Contains(t, out.String(), `"`+resourceGroupShowID+`"`)
assert.Empty(t, err.String(), "STDERR should be empty")
assert.Equal(t, 0, exitcode, "EXITCODE is not the expected one")
})
}

func TestResourceGroupDeleteNoInput(t *testing.T) {
out, err, exitcode := LaceworkCLIWithTOMLConfig("resource-group", "delete")
assert.Empty(t, out.String(), "STDOUT should be empty")
assert.Contains(t, err.String(), "ERROR accepts 1 arg(s), received 0")
assert.Equal(t, 1, exitcode, "EXITCODE is not the expected one")
}

func TestResourceGroupDelete(t *testing.T) {
// setup resource group
resourceGroupID, err := createResourceGroup()
if err != nil && !strings.Contains(err.Error(), "already exists in the account") {
assert.FailNow(t, err.Error())
}

// delete resource group
out, stderr, exitcode := LaceworkCLIWithTOMLConfig("resource-group", "delete", resourceGroupID)
assert.Contains(t, out.String(), "The resource group was deleted.")
assert.Empty(t, stderr.String(), "STDERR should be empty")
assert.Equal(t, 0, exitcode, "EXITCODE is not the expected one")
}

0 comments on commit 7603370

Please sign in to comment.