Skip to content

Commit

Permalink
docs: cluster scanner first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
caroldelwing committed Oct 29, 2024
1 parent 967e7bc commit 5b16fd7
Show file tree
Hide file tree
Showing 7 changed files with 301 additions and 0 deletions.
57 changes: 57 additions & 0 deletions scripts/cluster-scanner/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Cluster Scanner

The **Cluster Scanner** tool uses the Palette Go SDK to scan your Palette environment and identify clusters that have been active for more than 24 hours.

## Prerequisites

- Go version 1.22.5 or later
- Git
- The `palette-samples` repository available locally
- A Palette acount
- A Palette API key

## Usage

1. Open a terminal window and export your Palette URL. Replace `<your-palette-url>` with your Palette URL, for example, `console.spectrocloud.com`.

```shell
export PALETTE_HOST=<your-palette-url>
```

2. Export your Palette API key. Replace `<your-palette-api-key>` with your Palette API key.

```shell
export PALETTE_API_KEY=<your-palette-api-key>
```

3. To scan a specific project, export the project's UID. Replace `<your-palette-project>` with the Palette project UID. If no project is provided, the tool assumes a tenant scope and scans clusters across all projects.

```shell
export PALETTE_PROJECT_UID=<your-palette-project>
```

4. Navigate to the `cluster-scanner` folder.

```shell
cd cluster-scanner
```

5. Issue the command below to download the required Palette SDK modules.

```shell
go get
```

6. Execute the `cluster-scanner` application.

```shell
go run .
```

The application will print the clusters that have been active in your Palette environment for more than 24 hours.

```text hideClipboard
time=2024-10-28T21:21:47.516-04:00 level=INFO msg="Setting scope to tenant."
time=2024-10-28T21:21:47.516-04:00 level=INFO msg="Searching for clusters..."
time=2024-10-28T21:21:48.297-04:00 level=INFO msg="The aws cluster named aws-test has been running for 2 weeks 6 days 2 hours. Are you sure you need this cluster?"
```
38 changes: 38 additions & 0 deletions scripts/cluster-scanner/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module github.com/spectrocloud/palette-samples/cluster-scanner

go 1.22.5

toolchain go1.22.8

require (
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/go-errors/errors v1.5.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/analysis v0.23.0 // indirect
github.com/go-openapi/errors v0.22.0 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/loads v0.22.0 // indirect
github.com/go-openapi/runtime v0.28.0 // indirect
github.com/go-openapi/spec v0.21.0 // indirect
github.com/go-openapi/strfmt v0.23.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-openapi/validate v0.24.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spectrocloud/palette-sdk-go v0.0.0-20240930211255-e224a905d31a // indirect
go.mongodb.org/mongo-driver v1.16.0 // indirect
go.opentelemetry.io/otel v1.28.0 // indirect
go.opentelemetry.io/otel/metric v1.28.0 // indirect
go.opentelemetry.io/otel/trace v1.28.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.22.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
70 changes: 70 additions & 0 deletions scripts/cluster-scanner/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w=
github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco=
github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs=
github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ=
github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc=
github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c=
github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=
github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spectrocloud/palette-sdk-go v0.0.0-20240930211255-e224a905d31a h1:u1itx2mJzS9VCjVRr3cXqSnJpBxELSay5pdgFHIhz8w=
github.com/spectrocloud/palette-sdk-go v0.0.0-20240930211255-e224a905d31a/go.mod h1:dSlNvDS0qwUWTbrYI6P8x981mcbbRHFrBg67v5zl81U=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
go.mongodb.org/mongo-driver v1.16.0 h1:tpRsfBJMROVHKpdGyc1BBEzzjDUWjItxbVSZ8Ls4BQ4=
go.mongodb.org/mongo-driver v1.16.0/go.mod h1:oB6AhJQvFQL4LEHyXi6aJzQJtBiTQHiAd83l0GdFaiw=
go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
32 changes: 32 additions & 0 deletions scripts/cluster-scanner/internal/format_age.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package internal

import (
"fmt"
"time"
)

// Format the cluster age using weeks, days, and hours
func FormatAge (clusterAge time.Duration) (int, int, int) {
const hoursPerWeek = 168
weeks := int(clusterAge.Hours() / hoursPerWeek)
remainingHours := int(clusterAge.Hours() - float64((weeks * hoursPerWeek)))
days := int(remainingHours / 24)
hours := int(remainingHours % 24)
return weeks, days, hours
}

// Return the cluster age as a formatted string
func PrintFormattedAge (clusterAge time.Duration) (string) {
weeks, days, hours := FormatAge(clusterAge)
formattedString := ""
if weeks > 0 {
formattedString += fmt.Sprint(weeks) + " weeks "
}
if days > 0 {
formattedString += fmt.Sprint(days) + " days "
}
if hours > 0 {
formattedString += fmt.Sprint(hours) + " hours"
}
return formattedString
}
16 changes: 16 additions & 0 deletions scripts/cluster-scanner/internal/search_clusters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package internal

import (
"log/slog"

"github.com/spectrocloud/palette-sdk-go/api/models"
"github.com/spectrocloud/palette-sdk-go/client"
)

func SearchClusters (paletteClient *client.V1Client, logger *slog.Logger) ([]*models.V1SpectroClusterSummary, error) {
// Search for clusters
logger.Info("Searching for clusters...")
clusters, err := paletteClient.SearchClusterSummaries(&models.V1SearchFilterSpec{}, []*models.V1SearchFilterSortSpec{})

return clusters, err
}
30 changes: 30 additions & 0 deletions scripts/cluster-scanner/internal/search_old_clusters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package internal

import (
"fmt"
"log/slog"
"time"

"github.com/spectrocloud/palette-sdk-go/api/models"
)

func SearchOldClusters (clusters []*models.V1SpectroClusterSummary, logger *slog.Logger) bool {
// Variable to keep track of any found clusters older than 24h
foundOldCluster := false

// List the clusters that are running for more than 24h
for _, cluster := range clusters {
creationTime := cluster.Metadata.CreationTimestamp
timeValue := time.Time(creationTime)
timeNow := time.Now()
clusterAge := timeNow.Sub(timeValue)

if clusterAge.Hours() >= 24 {
foundOldCluster = true
message := fmt.Sprintf("The %s cluster named %s has been running for %s. Are you sure you need this cluster?", cluster.SpecSummary.CloudConfig.CloudType, cluster.Metadata.Name, PrintFormattedAge(clusterAge))
logger.Info(message)
}
}

return foundOldCluster
}
58 changes: 58 additions & 0 deletions scripts/cluster-scanner/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package main

import (
"log/slog"
"os"

"github.com/spectrocloud/palette-samples/cluster-scanner/internal"
"github.com/spectrocloud/palette-sdk-go/client"
)

func main() {

// Read environment variables
host := os.Getenv("PALETTE_HOST")
apiKey := os.Getenv("PALETTE_API_KEY")
projectUid := os.Getenv("PALETTE_PROJECT_UID")

logger := slog.New(slog.NewTextHandler(os.Stdout, nil))


if host == "" || apiKey == "" {
logger.Error("You must specify the PALETTE_HOST and PALETTE_API_KEY environment variables.")
os.Exit(1)
}

// Initialize a Palette client
paletteClient := client.New(
client.WithPaletteURI(host),
client.WithAPIKey(apiKey),
)

if projectUid != "" {
client.WithScopeProject(projectUid)(paletteClient)
logger.Info("Setting scope to project.")
} else {
client.WithScopeTenant()(paletteClient)
logger.Info("Setting scope to tenant.")
}

// Search for clusters
clusters, err := internal.SearchClusters(paletteClient, logger)
if err != nil {
logger.Error("Failed to search cluster summaries", "error", err)
os.Exit(2)
}

// Check active clusters
if len(clusters) == 0 {
logger.Warn("There are no clusters running.")
return
}

foundOldCluster := internal.SearchOldClusters(clusters, logger)

if !foundOldCluster {
logger.Info("There are no clusters running for more than 24 hours.")
}
}

0 comments on commit 5b16fd7

Please sign in to comment.