diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9fd542fef..591bd8dca 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -204,7 +204,7 @@ An example configuration entry for configuring a Google Cloud account in the **` [[gcp]] name="production" source="ENVIRONMENT_VARIABLES" -# path=./path/to/credentials/file specify if 'CREDENTIALS_FILE' is used as source +# path="./path/to/credentials/file" specify if 'CREDENTIALS_FILE' is used as source profile="production" ``` diff --git a/docs/configuration/cloud-providers/aws.mdx b/docs/configuration/cloud-providers/aws.mdx index 5813009a1..a924962c5 100644 --- a/docs/configuration/cloud-providers/aws.mdx +++ b/docs/configuration/cloud-providers/aws.mdx @@ -32,6 +32,7 @@ sidebar_label: Amazon Web Services - IAM policies - IAM roles - IAM SAML providers + - Kinesis Data Streams - KMS keys - Lambda functions - RDS clusters @@ -97,19 +98,19 @@ Add to config.toml file [[aws]] name="sandbox" source="CREDENTIALS_FILE" -path=./path/to/credentials/file +path="./path/to/credentials/file" profile="default" [[aws]] name="staging" source="CREDENTIALS_FILE" -path=./path/to/credentials/file +path="./path/to/credentials/file" profile="staging-account" [[gcp]] name="production" source="ENVIRONMENT_VARIABLES" -# path=./path/to/credentials/file specify if CREDENTIALS_FILE is used +# path="./path/to/credentials/file" specify if CREDENTIALS_FILE is used profile="production" [postgres] @@ -136,7 +137,7 @@ profile="production" [[aws]] name="sandbox" source="CREDENTIALS_FILE" -path=./path/to/credentials/file +path="./path/to/credentials/file" profile="default" ``` ### Credentials file @@ -502,4 +503,4 @@ metadata: volumes: - name: test-volume configMap: - name: aws-configmap \ No newline at end of file + name: aws-configmap diff --git a/docs/getting-started/quickstart.mdx b/docs/getting-started/quickstart.mdx index 2104a2a34..913d177a9 100644 --- a/docs/getting-started/quickstart.mdx +++ b/docs/getting-started/quickstart.mdx @@ -56,19 +56,19 @@ The reason for this external data persistence is to improve the filtering, sorti [[aws]] name="sandbox" source="CREDENTIALS_FILE" -path=./path/to/credentials/file +path="./path/to/credentials/file" profile="default" [[aws]] name="staging" source="CREDENTIALS_FILE" -path=./path/to/credentials/file +path="./path/to/credentials/file" profile="staging-account" [[gcp]] name="production" source="ENVIRONMENT_VARIABLES" -# path=./path/to/credentials/file specify if CREDENTIALS_FILE is used +# path="./path/to/credentials/file" specify if CREDENTIALS_FILE is used profile="production" [postgres] diff --git a/providers/k8s/core/namespaces.go b/providers/k8s/core/namespaces.go new file mode 100644 index 000000000..829c8b2f6 --- /dev/null +++ b/providers/k8s/core/namespaces.go @@ -0,0 +1,77 @@ +package core + +import ( + "context" + "time" + + log "github.com/sirupsen/logrus" + + "github.com/tailwarden/komiser/models" + "github.com/tailwarden/komiser/providers" + oc "github.com/tailwarden/komiser/providers/k8s/opencost" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func Namespaces(ctx context.Context, client providers.ProviderClient) ([]models.Resource, error) { + resources := make([]models.Resource, 0) + + var config metav1.ListOptions + + opencostEnabled := true + namespacesCost, err := oc.GetOpencostInfo(client.K8sClient.OpencostBaseUrl, "namespace") + if err != nil { + log.Errorf("ERROR: Couldn't get namespaces info from OpenCost: %v", err) + log.Warn("Opencost disabled") + opencostEnabled = false + } + + for { + res, err := client.K8sClient.Client.CoreV1().Namespaces().List(ctx, config) + if err != nil { + return nil, err + } + + for _, namespace := range res.Items { + tags := make([]models.Tag, 0) + + for key, value := range namespace.Labels { + tags = append(tags, models.Tag{ + Key: key, + Value: value, + }) + } + + cost := 0.0 + if opencostEnabled { + cost = namespacesCost[namespace.Name].TotalCost + } + + resources = append(resources, models.Resource{ + Provider: "Kubernetes", + Account: client.Name, + Service: "Namespace", + ResourceId: string(namespace.UID), + Name: namespace.Name, + Region: namespace.Namespace, + Cost: cost, + CreatedAt: namespace.CreationTimestamp.Time, + FetchedAt: time.Now(), + Tags: tags, + }) + } + + if res.GetContinue() == "" { + break + } + + config.Continue = res.GetContinue() + } + + log.WithFields(log.Fields{ + "provider": "Kubernetes", + "account": client.Name, + "service": "Namespace", + "resources": len(resources), + }).Info("Fetched resources") + return resources, nil +} diff --git a/providers/k8s/core/services.go b/providers/k8s/core/services.go index f4b1a7ce7..ae0127490 100644 --- a/providers/k8s/core/services.go +++ b/providers/k8s/core/services.go @@ -8,6 +8,7 @@ import ( . "github.com/tailwarden/komiser/models" "github.com/tailwarden/komiser/providers" + oc "github.com/tailwarden/komiser/providers/k8s/opencost" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -16,6 +17,14 @@ func Services(ctx context.Context, client providers.ProviderClient) ([]Resource, var config metav1.ListOptions + opencostEnabled := true + serviceCost, err := oc.GetOpencostInfo(client.K8sClient.OpencostBaseUrl, "service") + if err != nil { + log.Errorf("ERROR: Couldn't get service info from OpenCost: %v", err) + log.Warn("Opencost disabled") + opencostEnabled = false + } + for { res, err := client.K8sClient.Client.CoreV1().Services("").List(ctx, config) if err != nil { @@ -32,6 +41,11 @@ func Services(ctx context.Context, client providers.ProviderClient) ([]Resource, }) } + cost := 0.0 + if opencostEnabled { + cost = serviceCost[service.Name].TotalCost + } + resources = append(resources, Resource{ Provider: "Kubernetes", Account: client.Name, @@ -39,7 +53,7 @@ func Services(ctx context.Context, client providers.ProviderClient) ([]Resource, ResourceId: string(service.UID), Name: service.Name, Region: service.Namespace, - Cost: 0, + Cost: cost, CreatedAt: service.CreationTimestamp.Time, FetchedAt: time.Now(), Tags: tags, diff --git a/providers/k8s/k8s.go b/providers/k8s/k8s.go index 6d675361d..3b52335b7 100644 --- a/providers/k8s/k8s.go +++ b/providers/k8s/k8s.go @@ -21,6 +21,7 @@ func listOfSupportedServices() []providers.FetchDataFunction { core.PersistentVolumeClaims, core.ServiceAccounts, core.Nodes, + core.Namespaces, } }