Skip to content

Commit

Permalink
Merge pull request #420 from npellegrin/feature/iot-sitewise
Browse files Browse the repository at this point in the history
feat(iotsitewise): add portal, project, gateway, dashboard, asset, asset model and access policy
  • Loading branch information
ekristen authored Nov 18, 2024
2 parents b830a09 + d3574f4 commit 674525d
Show file tree
Hide file tree
Showing 7 changed files with 782 additions and 0 deletions.
148 changes: 148 additions & 0 deletions resources/iotsitewise-access-policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package resources

import (
"context"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/iotsitewise"

"github.com/ekristen/libnuke/pkg/registry"
"github.com/ekristen/libnuke/pkg/resource"
"github.com/ekristen/libnuke/pkg/types"

"github.com/ekristen/aws-nuke/v3/pkg/nuke"
)

const IoTSiteWiseAccessPolicyResource = "IoTSiteWiseAccessPolicy"

func init() {
registry.Register(&registry.Registration{
Name: IoTSiteWiseAccessPolicyResource,
Scope: nuke.Account,
Lister: &IoTSiteWiseAccessPolicyLister{},
})
}

type IoTSiteWiseAccessPolicyLister struct{}

func (l *IoTSiteWiseAccessPolicyLister) List(_ context.Context, o interface{}) ([]resource.Resource, error) { //nolint:gocyclo
opts := o.(*nuke.ListerOpts)

svc := iotsitewise.New(opts.Session)
resources := make([]resource.Resource, 0)

// Policies can be attached either to portal or projects
// List portal and portal policies
listPortalsParams := &iotsitewise.ListPortalsInput{
MaxResults: aws.Int64(25),
}
for {
listPortalsResp, err := svc.ListPortals(listPortalsParams)
if err != nil {
return nil, err
}
for _, portalItem := range listPortalsResp.PortalSummaries {
// Got portals
listProjectsParams := &iotsitewise.ListProjectsInput{
PortalId: portalItem.Id,
MaxResults: aws.Int64(25),
}

// List portal policies
listPortalPoliciesParam := &iotsitewise.ListAccessPoliciesInput{
ResourceId: portalItem.Id,
ResourceType: &([]string{string(iotsitewise.ResourceTypePortal)}[0]),
MaxResults: aws.Int64(25),
}

for {
listPortalPoliciesResp, err := svc.ListAccessPolicies(listPortalPoliciesParam)
if err != nil {
return nil, err
}
for _, item := range listPortalPoliciesResp.AccessPolicySummaries {
resources = append(resources, &IoTSiteWiseAccessPolicy{
svc: svc,
ID: item.Id,
})
}

if listPortalPoliciesResp.NextToken == nil {
break
}

listPortalPoliciesParam.NextToken = listPortalPoliciesResp.NextToken
}

// will also search inside projects
for {
listProjectsResp, err := svc.ListProjects(listProjectsParams)
if err != nil {
return nil, err
}
for _, projectItem := range listProjectsResp.ProjectSummaries {
// List project policies
listProjectPoliciesParams := &iotsitewise.ListAccessPoliciesInput{
ResourceId: projectItem.Id,
ResourceType: &([]string{string(iotsitewise.ResourceTypeProject)}[0]),
MaxResults: aws.Int64(25),
}

for {
listProjectPoliciesResp, err := svc.ListAccessPolicies(listProjectPoliciesParams)
if err != nil {
return nil, err
}
for _, item := range listProjectPoliciesResp.AccessPolicySummaries {
resources = append(resources, &IoTSiteWiseAccessPolicy{
svc: svc,
ID: item.Id,
})
}

if listProjectPoliciesResp.NextToken == nil {
break
}

listProjectPoliciesParams.NextToken = listProjectPoliciesResp.NextToken
}
}

if listProjectsResp.NextToken == nil {
break
}

listProjectsParams.NextToken = listProjectsResp.NextToken
}
}

if listPortalsResp.NextToken == nil {
break
}

listPortalsParams.NextToken = listPortalsResp.NextToken
}

return resources, nil
}

type IoTSiteWiseAccessPolicy struct {
svc *iotsitewise.IoTSiteWise
ID *string
}

func (r *IoTSiteWiseAccessPolicy) Properties() types.Properties {
return types.NewPropertiesFromStruct(r)
}

func (r *IoTSiteWiseAccessPolicy) Remove(_ context.Context) error {
_, err := r.svc.DeleteAccessPolicy(&iotsitewise.DeleteAccessPolicyInput{
AccessPolicyId: r.ID,
})

return err
}

func (r *IoTSiteWiseAccessPolicy) String() string {
return *r.ID
}
95 changes: 95 additions & 0 deletions resources/iotsitewise-asset-model.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package resources

import (
"context"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/iotsitewise"

"github.com/ekristen/libnuke/pkg/registry"
"github.com/ekristen/libnuke/pkg/resource"
"github.com/ekristen/libnuke/pkg/types"

"github.com/ekristen/aws-nuke/v3/pkg/nuke"
)

const IoTSiteWiseAssetModelResource = "IoTSiteWiseAssetModel"

func init() {
registry.Register(&registry.Registration{
Name: IoTSiteWiseAssetModelResource,
Scope: nuke.Account,
Lister: &IoTSiteWiseAssetModelLister{},
DependsOn: []string{
IoTSiteWiseAssetResource,
},
})
}

type IoTSiteWiseAssetModelLister struct{}

func (l *IoTSiteWiseAssetModelLister) List(_ context.Context, o interface{}) ([]resource.Resource, error) {
opts := o.(*nuke.ListerOpts)

svc := iotsitewise.New(opts.Session)
resources := make([]resource.Resource, 0)

params := &iotsitewise.ListAssetModelsInput{
MaxResults: aws.Int64(25),
}

for {
resp, err := svc.ListAssetModels(params)
if err != nil {
return nil, err
}
for _, item := range resp.AssetModelSummaries {
tagResp, err := svc.ListTagsForResource(
&iotsitewise.ListTagsForResourceInput{
ResourceArn: item.Arn,
})
if err != nil {
return nil, err
}

resources = append(resources, &IoTSiteWiseAssetModel{
svc: svc,
ID: item.Id,
Name: item.Name,
Status: item.Status.State,
Tags: tagResp.Tags,
})
}

if resp.NextToken == nil {
break
}

params.NextToken = resp.NextToken
}

return resources, nil
}

type IoTSiteWiseAssetModel struct {
svc *iotsitewise.IoTSiteWise
ID *string
Name *string
Status *string
Tags map[string]*string
}

func (r *IoTSiteWiseAssetModel) Properties() types.Properties {
return types.NewPropertiesFromStruct(r)
}

func (r *IoTSiteWiseAssetModel) Remove(_ context.Context) error {
_, err := r.svc.DeleteAssetModel(&iotsitewise.DeleteAssetModelInput{
AssetModelId: r.ID,
})
return err
}

func (r *IoTSiteWiseAssetModel) String() string {
return *r.ID
}
146 changes: 146 additions & 0 deletions resources/iotsitewise-asset.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package resources

import (
"context"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/iotsitewise"

"github.com/ekristen/libnuke/pkg/registry"
"github.com/ekristen/libnuke/pkg/resource"
"github.com/ekristen/libnuke/pkg/types"

"github.com/ekristen/aws-nuke/v3/pkg/nuke"
)

const IoTSiteWiseAssetResource = "IoTSiteWiseAsset"

func init() {
registry.Register(&registry.Registration{
Name: IoTSiteWiseAssetResource,
Scope: nuke.Account,
Lister: &IoTSiteWiseAssetLister{},
})
}

type IoTSiteWiseAssetLister struct{}

func (l *IoTSiteWiseAssetLister) List(_ context.Context, o interface{}) ([]resource.Resource, error) {
opts := o.(*nuke.ListerOpts)

svc := iotsitewise.New(opts.Session)
resources := make([]resource.Resource, 0)

assetModelSummaries, err := ListAssetModels(svc)
if err != nil {
return nil, err
}

for _, assetModelSummary := range assetModelSummaries {
params := &iotsitewise.ListAssetsInput{
AssetModelId: assetModelSummary.Id,
MaxResults: aws.Int64(25),
}

for {
resp, err := svc.ListAssets(params)
if err != nil {
return nil, err
}
for _, item := range resp.AssetSummaries {
tagResp, err := svc.ListTagsForResource(
&iotsitewise.ListTagsForResourceInput{
ResourceArn: item.Arn,
})
if err != nil {
return nil, err
}

resources = append(resources, &IoTSiteWiseAsset{
svc: svc,
ID: item.Id,
Name: item.Name,
Status: item.Status.State,
Tags: tagResp.Tags,
})
}

if resp.NextToken == nil {
break
}

params.NextToken = resp.NextToken
}
}

return resources, nil
}

// Utility function to get models, allowing to scan for assets
func ListAssetModels(svc *iotsitewise.IoTSiteWise) ([]*iotsitewise.AssetModelSummary, error) {
resources := make([]*iotsitewise.AssetModelSummary, 0)
params := &iotsitewise.ListAssetModelsInput{
MaxResults: aws.Int64(25),
}
for {
resp, err := svc.ListAssetModels(params)
if err != nil {
return nil, err
}
resources = append(resources, resp.AssetModelSummaries...)
if resp.NextToken == nil {
break
}
params.NextToken = resp.NextToken
}
return resources, nil
}

type IoTSiteWiseAsset struct {
svc *iotsitewise.IoTSiteWise
ID *string
Name *string
Status *string
Tags map[string]*string
}

func (r *IoTSiteWiseAsset) Properties() types.Properties {
return types.NewPropertiesFromStruct(r)
}

func (r *IoTSiteWiseAsset) Remove(_ context.Context) error {
associatedAssets, err := r.svc.ListAssociatedAssets(&iotsitewise.ListAssociatedAssetsInput{
AssetId: r.ID,
})
if err != nil {
return err
}
assetDescription, err := r.svc.DescribeAsset(&iotsitewise.DescribeAssetInput{
AssetId: r.ID,
})
if err != nil {
return err
}

// If asset is associated, dissociate before delete
for _, assetHierarchy := range assetDescription.AssetHierarchies {
for _, childAsset := range associatedAssets.AssetSummaries {
// Could fail if hierarchy it not the correct one, ignore it
_, _ = r.svc.DisassociateAssets(&iotsitewise.DisassociateAssetsInput{
AssetId: r.ID,
ChildAssetId: childAsset.Id,
HierarchyId: assetHierarchy.Id,
})
}
}

_, err = r.svc.DeleteAsset(&iotsitewise.DeleteAssetInput{
AssetId: r.ID,
})

return err
}

func (r *IoTSiteWiseAsset) String() string {
return *r.ID
}
Loading

0 comments on commit 674525d

Please sign in to comment.