Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Editor configuration, see http://editorconfig.org
root = true

[*]
charset = utf-8
insert_final_newline = true
trim_trailing_whitespace = true

# Go files use tabs
[*.go]
indent_style = tab
indent_size = 4

# Frontend files (TypeScript, JavaScript, CSS, HTML, JSON, YAML)
[*.{ts,tsx,js,jsx,css,html,json,yaml,yml}]
indent_style = space
indent_size = 2

# Makefiles require tabs
[Makefile]
indent_style = tab

# Markdown and snapshots
[*.md]
max_line_length = off
trim_trailing_whitespace = false

[*.snap]
max_line_length = off
trim_trailing_whitespace = false
51 changes: 51 additions & 0 deletions .github/workflows/build-container-images.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -207,16 +207,67 @@ jobs:
run: |
podman logout quay.io

console:
runs-on: ubuntu-latest
needs: setup
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v5

- name: Login to Quay.io
run: |
echo "${{ secrets.QUAY_PASSWORD }}" | podman login quay.io -u "${{ secrets.QUAY_USERNAME }}" --password-stdin

- name: Container image building
run: |
echo "Building ClusterIQ Console (${{ needs.setup.outputs.BRANCH }}/${{ needs.setup.outputs.SHA_COMMIT }})"
podman build \
--platform linux/amd64 \
--build-arg VERSION=${{ needs.setup.outputs.GIT_TAG }} \
--build-arg COMMIT=${{ needs.setup.outputs.SHA_COMMIT }} \
-t quay.io/${{ secrets.QUAY_ORG_NAME }}/cluster-iq-console:${{ needs.setup.outputs.SHA_COMMIT }} \
-f ./console/deployments/containerfiles/Containerfile ./console

- name: Pushing Hash based image
run: |
podman push quay.io/${{ secrets.QUAY_ORG_NAME }}/cluster-iq-console:${{ needs.setup.outputs.SHA_COMMIT }}

- name: Tagging and Pushing Latest Image
if: ${{ needs.setup.outputs.LATEST_TAG != '' && needs.setup.outputs.LATEST_TAG != null }}
run: |
podman tag \
quay.io/${{ secrets.QUAY_ORG_NAME }}/cluster-iq-console:${{ needs.setup.outputs.SHA_COMMIT }} \
quay.io/${{ secrets.QUAY_ORG_NAME }}/cluster-iq-console:${{ needs.setup.outputs.LATEST_TAG }}
podman push quay.io/${{ secrets.QUAY_ORG_NAME }}/cluster-iq-console:${{ needs.setup.outputs.LATEST_TAG }}

- name: Tagging and Pushing GitTag based image
if: ${{ needs.setup.outputs.GIT_TAG != '' && needs.setup.outputs.GIT_TAG != null }}
run: |
echo "Building Tagged version image: ${{ needs.setup.outputs.GIT_TAG }}"
podman tag \
quay.io/${{ secrets.QUAY_ORG_NAME }}/cluster-iq-console:${{ needs.setup.outputs.SHA_COMMIT }} \
quay.io/${{ secrets.QUAY_ORG_NAME }}/cluster-iq-console:${{ needs.setup.outputs.GIT_TAG }}
podman push quay.io/${{ secrets.QUAY_ORG_NAME }}/cluster-iq-console:${{ needs.setup.outputs.GIT_TAG }}

- name: Logout from Quay.io
run: |
podman logout quay.io

final:
runs-on: ubuntu-latest
needs:
- setup
- api
- agent
- scanner
- console
steps:
- name: Validating
run: |
podman pull quay.io/${{ secrets.QUAY_ORG_NAME }}/cluster-iq-api:${{ needs.setup.outputs.SHA_COMMIT }}
podman pull quay.io/${{ secrets.QUAY_ORG_NAME }}/cluster-iq-agent:${{ needs.setup.outputs.SHA_COMMIT }}
podman pull quay.io/${{ secrets.QUAY_ORG_NAME }}/cluster-iq-scanner:${{ needs.setup.outputs.SHA_COMMIT }}
podman pull quay.io/${{ secrets.QUAY_ORG_NAME }}/cluster-iq-console:${{ needs.setup.outputs.SHA_COMMIT }}
29 changes: 29 additions & 0 deletions .github/workflows/validate-pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,35 @@ jobs:
only-new-issues: true
args: --whole-files

console-lint:
name: Console Lint
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./console
steps:
- name: Checkout
uses: actions/checkout@v5

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 18
cache: 'npm'
cache-dependency-path: console/package-lock.json

- name: Install dependencies
run: npm ci

- name: Code Prettier
run: make ts-prettier

- name: Code Linter
run: make ts-eslint

- name: TypeScript type check
run: make ts-tsc

call-unit-tests:
name: Go Unit tests
needs:
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,9 @@ go.work.sum
# IDE files
.idea/
.vscode/

# Console (frontend)
console/node_modules/
console/dist/
console/dist-ssr/
console/coverage/
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
18
17 changes: 15 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ This file provides guidance to Claude Code when working with this repository.
**ClusterIQ** is an inventory and cost estimation platform for OpenShift clusters across multi-cloud environments (currently AWS only). It provides automated discovery, cost tracking, and lifecycle management.

**Architecture Components:**
1. **Scanner**: CronJob that discovers cloud resources using "Stocker" pattern
1. **Scanner**: Long-running gRPC service that discovers cloud resources using "Stocker" pattern
2. **API Server**: REST API (Gin framework) for inventory queries and cluster operations
3. **Agent**: gRPC service handling cluster power operations (instant, scheduled, recurring)
4. **Console**: React/TypeScript web UI (PatternFly, Vite)

**Repository Structure:**
```
Expand All @@ -23,6 +24,10 @@ internal/
├── services/ # Business logic
├── api/handlers/ # HTTP handlers
└── models/ # DTO, DB, domain models
console/ # Web UI (React/TypeScript/Vite/PatternFly)
├── src/ # Application source code
├── deployments/ # Console Containerfile
└── nginx/ # NGINX config template and startup script
db/sql/ # Schema definitions (init.sql, cron.sql)
test/integration/ # Integration tests
```
Expand Down Expand Up @@ -53,6 +58,13 @@ make lint-staged # Lint staged files only
# Code Generation
make generate-converters # Goverter (DB to DTO)
make swagger-doc # OpenAPI docs

# Console (frontend)
make console-install # Install npm dependencies
make console-build # Build console locally
make console-start-dev # Vite dev server (port 3000)
make console-lint # Run prettier + eslint + tsc
make build-console # Build console container image
```

## Architecture Patterns
Expand Down Expand Up @@ -111,12 +123,13 @@ go tool cover -html=coverage.out -o coverage.html # Visual
## Development Workflow

1. Make code changes
2. Run `make lint-staged` before committing
2. Run `make lint-staged` before committing (Go), `make console-lint` (Console)
3. Run relevant tests: `make go-unit-tests`
4. For API changes: update Swagger with `make swagger-doc`
5. For DB changes: update `db/sql/init.sql` or add data migration in `doc/releases/`
6. For protobuf changes: `make local-build-agent`
7. For goverter changes: `make generate-converters`
8. For console changes: run `make console-lint` and test in browser via `make console-start-dev`

**Commit Convention:**
- Use conventional commits format: `type(scope): brief description`
Expand Down
35 changes: 33 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ AGENT_PROTO_PATH ?= ./cmd/agent/proto/agent.proto
PGSQL_IMG_NAME ?= $(PROJECT_NAME)-pgsql
PGSQL_IMAGE ?= $(REGISTRY)/$(REGISTRY_REPO)/$(PGSQL_IMG_NAME)
PGSQL_CONTAINERFILE ?= ./$(DEPLOYMENTS_DIR)/containerfiles/Containerfile-pgsql
CONSOLE_DIR ?= ./console
CONSOLE_IMG_NAME ?= $(PROJECT_NAME)-console
CONSOLE_IMAGE ?= $(REGISTRY)/$(REGISTRY_REPO)/$(CONSOLE_IMG_NAME)
CONSOLE_CONTAINERFILE ?= $(CONSOLE_DIR)/deployments/containerfiles/Containerfile

# Standard targets
all: ## Stop, build and start the development environment based on containers
Expand Down Expand Up @@ -89,10 +93,10 @@ local-build-agent: ## Build the agent binary
# Container based working targets
clean: ## Remove the container images
@echo "### [Cleaning Container images] ###"
@-$(CONTAINER_ENGINE) images | grep -e $(SCANNER_IMAGE) -e $(API_IMAGE) -e $(AGENT_IMAGE) -e $(PGSQL_IMAGE) | awk '{print $$3}' | xargs $(CONTAINER_ENGINE) rmi -f
@-$(CONTAINER_ENGINE) images | grep -e $(SCANNER_IMAGE) -e $(API_IMAGE) -e $(AGENT_IMAGE) -e $(PGSQL_IMAGE) -e $(CONSOLE_IMAGE) | awk '{print $$3}' | xargs $(CONTAINER_ENGINE) rmi -f

build: ## Build all container images
build: build-api build-scanner build-agent build-pgsql
build: build-api build-scanner build-agent build-pgsql build-console
build-api: generate-converters ## Build the API container image
@echo "### [Building API container image] ###"
@$(CONTAINER_ENGINE) build \
Expand Down Expand Up @@ -129,12 +133,22 @@ build-pgsql: ## Build the PGSQL container image
@$(CONTAINER_ENGINE) tag $(PGSQL_IMAGE):latest $(PGSQL_IMAGE):$(SHORT_COMMIT_HASH)
@echo "Build Successful"

build-console: ## Build the Console container image
@echo "### [Building Console container image] ###"
@$(CONTAINER_ENGINE) build \
--build-arg VERSION=$(VERSION) \
--build-arg COMMIT=$(SHORT_COMMIT_HASH) \
-t $(CONSOLE_IMAGE):latest -f $(CONSOLE_CONTAINERFILE) $(CONSOLE_DIR)
@$(CONTAINER_ENGINE) tag $(CONSOLE_IMAGE):latest $(CONSOLE_IMAGE):$(SHORT_COMMIT_HASH)
@echo "Build Successful"


# Development targets
start-dev: ## Start the container-based development environment
@echo "### [Starting dev environment] ###"
@$(CONTAINER_ENGINE)-compose -f $(DEPLOYMENTS_DIR)/compose/compose-devel.yaml up -d
@echo "### [Running dev environment] ###"
@echo "### [Console: http://localhost:8080 ] ###"
@echo "### [API: http://localhost:8081/api/v1/healthcheck ] ###"

stop-dev: ## Stop the container-based development environment
Expand Down Expand Up @@ -207,6 +221,23 @@ swagger-doc: ## Generate Swagger documentation for ClusterIQ API
@$(SWAGGER) init --generalInfo ./cmd/api/server.go --parseDependency --output ./cmd/api/docs


# Console targets (delegated to console/Makefile)
console-install: ## Install console dependencies
@$(MAKE) -C $(CONSOLE_DIR) local-install

console-build: ## Build console locally
@$(MAKE) -C $(CONSOLE_DIR) local-build

console-clean: ## Clean console build artifacts
@$(MAKE) -C $(CONSOLE_DIR) local-clean

console-start-dev: ## Start console dev server
@$(MAKE) -C $(CONSOLE_DIR) local-start-dev

console-lint: ## Run console linters (prettier + eslint + tsc)
@$(MAKE) -C $(CONSOLE_DIR) ts-test


# Set the default target to "help"
.DEFAULT_GOAL := help
# Help
Expand Down
44 changes: 35 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![Go Report Card](https://goreportcard.com/badge/github.com/RHEcosystemAppEng/cluster-iq)](https://goreportcard.com/report/github.com/RHEcosystemAppEng/cluster-iq)
[![Go Reference](https://pkg.go.dev/badge/github.com/RHEcosystemAppEng/cluster-iq.svg)](https://pkg.go.dev/github.com/RHEcosystemAppEng/cluster-iq)
![Version](https://img.shields.io/badge/version-0.5-blue)
![Version](https://img.shields.io/badge/version-0.6-blue)
![License](https://img.shields.io/badge/license-Apache--2.0-green)
---
[![Container image building](https://github.com/RHEcosystemAppEng/cluster-iq/actions/workflows/build-container-images.yaml/badge.svg)](https://github.com/RHEcosystemAppEng/cluster-iq/actions/workflows/build-container-images.yaml)
Expand All @@ -19,8 +19,8 @@ goal is to provide a continually updated inventory of clusters. This helps
users efficiently identify and manage their clusters, offering a simplified
approach to estimating costs and ensuring better resource management.

ClusterIQ has a Web UI called [ClusterIQ Console](https://github.com/RHEcosystemAppEng/cluster-iq-console).
Follow this [link](https://github.com/RHEcosystemAppEng/cluster-iq-console?tab=readme-ov-file#development-scripts) for installation instructions.
ClusterIQ includes a Web UI (Console) under the `console/` directory.
See the [Console](#console) section for development instructions.


## Supported cloud providers
Expand Down Expand Up @@ -138,11 +138,8 @@ For more information about the supported parameters, check the [Configuration Se
helm list -n $NAMESPACE
```

6. Once every pod is up and running, trigger the scanner manually for
initializing the inventory
```sh
oc create job --from=cronjob/scanner scanner-init -n $NAMESPACE
```
6. Once every pod is up and running, the scanner will automatically begin
discovering cloud resources.

### Uninstalling
To uninstall ClusterIQ Helm chart, use the following commands
Expand Down Expand Up @@ -206,7 +203,7 @@ make local-build-api
The Agent performs actions over the selected cloud resources. It only accepts
incoming requests from the API.

Currently, on release `v0.4`, the agent only supports Power On/Off clusters on AWS.
The Agent supports Power On/Off operations for clusters on AWS, including instant, scheduled, and recurring actions.

```shell
# Building in a container
Expand All @@ -216,6 +213,35 @@ make build-agent
make local-build-agent
```

## Console

The web console is a React/TypeScript application located under `console/`.
It provides the ClusterIQ Web UI with cluster inventory views, cost tracking, and action management.

### Prerequisites
- [Node.js](https://nodejs.org/) 18.x or higher
- [npm](https://www.npmjs.com/) 8.x or higher

### Development Commands
```shell
# Install console dependencies
make console-install

# Build console locally
make console-build

# Start console dev server (port 3000, proxies API to localhost:8081)
make console-start-dev

# Run console linters (prettier + eslint + tsc)
make console-lint

# Build console container image
make build-console
```

For more details, see `console/README.md`.

## Extra Documentation

The following documentation is available:
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.5
v0.6
10 changes: 10 additions & 0 deletions console/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.env
.git
.gitignore
*.md
dist
Dockerfile
Containerfile
Makefile
node_modules
npm-debug.log
1 change: 1 addition & 0 deletions console/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package.json
Loading