-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit fc675d8
Showing
17 changed files
with
835 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
version: 2 | ||
updates: | ||
- package-ecosystem: "gomod" | ||
directory: "/" | ||
schedule: | ||
interval: "weekly" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
name: goreleaser | ||
|
||
on: | ||
pull_request: | ||
push: | ||
|
||
permissions: | ||
contents: write | ||
|
||
jobs: | ||
goreleaser: | ||
env: | ||
GORELEASER_FLAGS: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- if: ${{ !startsWith(github.ref, 'refs/tags/20') }} | ||
run: echo "GORELEASER_FLAGS=--snapshot" >> $GITHUB_ENV | ||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
with: | ||
fetch-depth: 0 | ||
- name: Set up Go | ||
uses: actions/setup-go@v5 | ||
with: | ||
go-version: 1.22 | ||
- name: Run GoReleaser | ||
uses: goreleaser/goreleaser-action@v5 | ||
with: | ||
distribution: goreleaser | ||
version: latest | ||
args: release --clean ${{ env.GORELEASER_FLAGS }} | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
dist | ||
clibana |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
linters: | ||
enable-all: true | ||
disable: | ||
# Dont care: | ||
- exhaustruct | ||
- depguard | ||
- wrapcheck | ||
- tagalign | ||
# Deprecated: | ||
- execinquery | ||
- gomnd | ||
- perfsprint | ||
- gochecknoglobals | ||
|
||
issues: | ||
exclude-rules: [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# This is an example .goreleaser.yml file with some sensible defaults. | ||
# Make sure to check the documentation at https://goreleaser.com | ||
before: | ||
hooks: | ||
# You may remove this if you don't use go modules. | ||
- go mod tidy | ||
# you may remove this if you don't need go generate | ||
- go generate ./... | ||
builds: | ||
- env: | ||
- CGO_ENABLED=0 | ||
- GOEXPERIMENT=rangefunc | ||
goos: | ||
- linux | ||
- darwin | ||
- windows | ||
goarch: | ||
- amd64 | ||
- arm64 | ||
|
||
archives: | ||
- format: tar.gz | ||
# this name template makes the OS and Arch compatible with the results of uname. | ||
name_template: >- | ||
{{ .ProjectName }}_ {{- title .Os }}_ {{- if eq .Arch "amd64" }}x86_64 {{- else if eq .Arch "386" }}i386 {{- else }}{{ .Arch }}{{ end }} {{- if .Arm }}v{{ .Arm }}{{ end }} | ||
# use zip for windows archives | ||
format_overrides: | ||
- goos: windows | ||
format: zip | ||
checksum: | ||
name_template: 'checksums.txt' | ||
snapshot: | ||
name_template: "{{ incpatch .Version }}-next" | ||
changelog: | ||
sort: asc | ||
filters: | ||
exclude: | ||
- '^docs:' | ||
- '^test:' | ||
|
||
# The lines beneath this are called `modelines`. See `:help modeline` | ||
# Feel free to remove those if you don't want/use them. | ||
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json | ||
# vim: set ts=2 sw=2 tw=0 fo=cnqoj |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Clibana | ||
![GitHub release (with filter)](https://img.shields.io/github/v/release/ivoronin/clibana) | ||
[![Go Report Card](https://goreportcard.com/badge/github.com/ivoronin/clibana)](https://goreportcard.com/report/github.com/ivoronin/clibana) | ||
![GitHub last commit (branch)](https://img.shields.io/github/last-commit/ivoronin/clibana/main) | ||
![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/ivoronin/clibana/main.yml) | ||
![GitHub top language](https://img.shields.io/github/languages/top/ivoronin/clibana) | ||
|
||
## Description | ||
|
||
Clibana is a command-line interface (CLI) tool for OpenSearch that offers Kibana-like log searching and live tailing (`-f` support) capabilities. | ||
|
||
## Features | ||
|
||
- **Log Search**: Execute searches on multiple OpenSearch indices using Lucene query syntax. Clibana can output specified fields or export data in NDJSON format. | ||
- **Live Tailing**: Monitor logs in real-time using the `-f` option, similar to `tail -f`. | ||
- **Cluster Exploration**: List index information and field mappings. | ||
- **AWS and Basic Authentication**: Supports both AWS SigV4 and Basic Authentication methods. | ||
|
||
## Examples | ||
|
||
```bash | ||
clibana -H https://logs.internal -i "k8s.containers.*" search -s now-2h -e now-1h "kubernetes.pod_name:*nginx*" | ||
clibana -H https://logs.internal -i "k8s.containers.*" mappings | ||
clibana -H https://logs.internal -i "k8s.containers.*" indices | ||
``` | ||
|
||
Most options can be set using environment variables. Check `clibana` -h for additional details. | ||
|
||
### AWS Support | ||
|
||
1. Clibana supports the `aws://` scheme to specify an AWS Managed OpenSearch Domain name as a host, which will automatically resolve to its endpoint. Example: `clibana --host aws://logs-internal`. | ||
2. You can use your AWS credentials to authenticate to an AWS Managed OpenSearch Domain. Set the authentication type to `aws`: `clibana -a aws`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/aws/aws-sdk-go-v2/aws" | ||
awsconfig "github.com/aws/aws-sdk-go-v2/config" | ||
awsopensearch "github.com/aws/aws-sdk-go-v2/service/opensearch" | ||
"github.com/opensearch-project/opensearch-go/v2" | ||
"github.com/opensearch-project/opensearch-go/v2/signer/awsv2" | ||
) | ||
|
||
var awsConfig *aws.Config | ||
|
||
func awsInit() { | ||
if awsConfig == nil { | ||
config, err := awsconfig.LoadDefaultConfig(context.TODO()) | ||
if err != nil { | ||
FatalError(fmt.Errorf("failed to load AWS config: %w", err)) | ||
} | ||
|
||
awsConfig = &config | ||
} | ||
} | ||
|
||
func resolveAWSDomainEndpoint(domainName string) string { | ||
awsInit() | ||
|
||
aosClient := awsopensearch.NewFromConfig(*awsConfig) | ||
|
||
domain, err := aosClient.DescribeDomain(context.TODO(), &awsopensearch.DescribeDomainInput{ | ||
DomainName: &domainName, | ||
}) | ||
if err != nil { | ||
FatalError(fmt.Errorf("failed to describe OpenSearch domain: %w", err)) | ||
} | ||
|
||
var endpoint string | ||
|
||
switch { | ||
case domain.DomainStatus.EndpointV2 != nil: | ||
endpoint = *domain.DomainStatus.EndpointV2 | ||
case domain.DomainStatus.Endpoint != nil: | ||
endpoint = *domain.DomainStatus.Endpoint | ||
case domain.DomainStatus.Endpoints != nil: | ||
switch { | ||
case domain.DomainStatus.Endpoints["vpcv2"] != "": | ||
endpoint = domain.DomainStatus.Endpoints["vpcv2"] | ||
case domain.DomainStatus.Endpoints["vpc"] != "": | ||
endpoint = domain.DomainStatus.Endpoints["vpc"] | ||
} | ||
} | ||
|
||
if endpoint == "" { | ||
FatalError(fmt.Errorf("no endpoints found for OpenSearch domain: %s", domainName)) | ||
} | ||
|
||
return "https://" + endpoint | ||
} | ||
|
||
func buildAWSAuthClientConfig() opensearch.Config { | ||
awsInit() | ||
|
||
signer, err := awsv2.NewSigner(*awsConfig) | ||
if err != nil { | ||
FatalError(fmt.Errorf("failed to create AWS V4 signer: %w", err)) | ||
} | ||
|
||
return opensearch.Config{ | ||
Signer: signer, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"strings" | ||
"time" | ||
|
||
"github.com/opensearch-project/opensearch-go/v2" | ||
"github.com/opensearch-project/opensearch-go/v2/opensearchapi" | ||
) | ||
|
||
func buildClientConfig(clibanaConfig ClibanaConfig) opensearch.Config { | ||
var opensearchConfig opensearch.Config | ||
|
||
switch strings.ToLower(clibanaConfig.AuthType) { | ||
case AuthTypeAWS: | ||
opensearchConfig = buildAWSAuthClientConfig() | ||
case AuthTypeBasic: | ||
opensearchConfig = buildBasicAuthClientConfig(clibanaConfig) | ||
default: | ||
FatalError(fmt.Errorf("unsupported authentication type: %s", clibanaConfig.AuthType)) | ||
} | ||
|
||
opensearchConfig.Addresses = []string{clibanaConfig.Host} | ||
opensearchConfig.Transport = &http.Transport{ | ||
ResponseHeaderTimeout: ResponseTimeout * time.Second, | ||
} | ||
|
||
return opensearchConfig | ||
} | ||
|
||
func createClient(clibanaConfig ClibanaConfig) (*opensearch.Client, error) { | ||
if strings.HasPrefix(clibanaConfig.Host, "aws://") { | ||
domainName := strings.TrimPrefix(clibanaConfig.Host, "aws://") | ||
clibanaConfig.Host = resolveAWSDomainEndpoint(domainName) | ||
} | ||
|
||
return opensearch.NewClient(buildClientConfig(clibanaConfig)) | ||
} | ||
|
||
func buildBasicAuthClientConfig(config ClibanaConfig) opensearch.Config { | ||
if config.Username == "" || config.Password == "" { | ||
FatalError(fmt.Errorf("uusername and password must be provided for basic authentication")) | ||
} | ||
|
||
return opensearch.Config{ | ||
Username: config.Username, | ||
Password: config.Password, | ||
} | ||
} | ||
|
||
func doRequest[T any](client *opensearch.Client, request opensearchapi.Request) T { | ||
DebugLogger.Printf("Request: %+v\n", request) | ||
|
||
response, err := request.Do(context.TODO(), client) | ||
if err != nil { | ||
FatalError(fmt.Errorf("request failed: %w", err)) | ||
} | ||
|
||
defer response.Body.Close() | ||
|
||
DebugLogger.Printf("Response: %+v\n", response) | ||
|
||
if response.IsError() { | ||
FatalError(fmt.Errorf("request error: %s", response.String())) | ||
} | ||
|
||
var responseObj T | ||
|
||
if err := json.NewDecoder(response.Body).Decode(&responseObj); err != nil { | ||
FatalError(fmt.Errorf("error decoding response: %w", err)) | ||
} | ||
|
||
return responseObj | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package main | ||
|
||
import ( | ||
"strings" | ||
|
||
"github.com/alexflint/go-arg" | ||
) | ||
|
||
type SearchConfig struct { | ||
Fields fieldList `arg:"-o,env:CLIBANA_FIELDS" help:"Comma-separated list of fields to output"` | ||
Follow bool `arg:"-f" help:"Enable live tailing of logs"` | ||
Query string `arg:"positional" default:"*" help:"Query string"` | ||
Start string `arg:"-s" default:"now-5m" help:"Start time"` | ||
End string `arg:"-e" default:"now" help:"End time"` | ||
} | ||
|
||
type MappingsConfig struct { | ||
Quiet bool `arg:"-q" help:"Do not show headers"` | ||
} | ||
|
||
type IndicesConfig struct { | ||
Quiet bool `arg:"-q" help:"Do not show headers"` | ||
} | ||
|
||
type ClibanaConfig struct { | ||
Host string `arg:"-H,required,env:CLIBANA_HOST" help:"http[s]://host[:port] or aws://cluster-name"` | ||
Index string `arg:"-i,required,env:CLIBANA_INDEX" help:"Index pattern"` | ||
AuthType string `arg:"-a,env:CLIBANA_AUTH" default:"basic" help:"Authentication type: aws or basic"` | ||
Username string `arg:"-u,env:CLIBANA_USER" help:"Username for basic authentication"` | ||
Password string `arg:"-p,env:CLIBANA_PASSWORD" help:"Password for basic authentication"` | ||
Debug bool `arg:"-d,env:CLIBANA_DEBUG" help:"Enable debug output"` | ||
Search *SearchConfig `arg:"subcommand:search" help:"Search indices matching the index pattern"` | ||
Mappings *MappingsConfig `arg:"subcommand:mappings" help:"Show field mappings in the indices matching the index pattern"` | ||
Indices *IndicesConfig `arg:"subcommand:indices" help:"List indices matching the index pattern"` | ||
} | ||
|
||
func NewClibanaConfig() ClibanaConfig { | ||
var clibanaConfig ClibanaConfig | ||
|
||
arg.MustParse(&clibanaConfig) | ||
|
||
return clibanaConfig | ||
} | ||
|
||
func (ClibanaConfig) Description() string { | ||
return "Clibana - OpenSearch log tailer" | ||
} | ||
|
||
func (ClibanaConfig) Epilogue() string { | ||
return "For more information, see https://github.com/ivoronin/clibana" | ||
} | ||
|
||
type fieldList []string | ||
|
||
func (c *fieldList) UnmarshalText(text []byte) error { //nolint:unparam | ||
*c = strings.Split(string(text), ",") | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
module github.com/ivoronin/clibana | ||
|
||
go 1.22.4 | ||
|
||
require ( | ||
github.com/alexflint/go-arg v1.5.1 | ||
github.com/aws/aws-sdk-go-v2 v1.30.3 | ||
github.com/aws/aws-sdk-go-v2/config v1.27.27 | ||
github.com/aws/aws-sdk-go-v2/service/opensearch v1.39.2 | ||
github.com/opensearch-project/opensearch-go/v2 v2.3.0 | ||
) | ||
|
||
require ( | ||
github.com/alexflint/go-scalar v1.2.0 // indirect | ||
github.com/aws/aws-sdk-go-v2/credentials v1.17.27 // indirect | ||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 // indirect | ||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 // indirect | ||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 // indirect | ||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect | ||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 // indirect | ||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 // indirect | ||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.4 // indirect | ||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect | ||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect | ||
github.com/aws/smithy-go v1.20.3 // indirect | ||
) |
Oops, something went wrong.