-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature] Add elastic client #10
base: main
Are you sure you want to change the base?
Changes from 6 commits
4aabb04
57f9aba
532a72c
73dd0e7
d285229
56d9a75
9116ee5
67b7140
7db3f4f
c86b1b7
e15917c
89ce20c
88cc404
e4bb6ac
549301f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
package elastic_cloud | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"log" | ||
"os" | ||
"strconv" | ||
"strings" | ||
"time" | ||
|
||
"github.com/elastic/go-elasticsearch/v8" | ||
"github.com/elastic/go-elasticsearch/v8/esapi" | ||
"github.com/manifoldco/promptui" | ||
"github.com/urfave/cli/v2" | ||
|
||
envconfig "github.com/sethvargo/go-envconfig" | ||
ctrl "sigs.k8s.io/controller-runtime" | ||
) | ||
|
||
// Config for Elasticsearch client | ||
type EsConfig struct { | ||
ApiKey string `env:"EC_API_KEY"` | ||
CloudId string `env:"EC_CLOUD_ID"` | ||
} | ||
|
||
type IndexSettings struct { | ||
IndexItem struct { | ||
IndexDetail struct { | ||
CreationDate string `json:"creation_date"` | ||
} `json:"index"` | ||
} `json:"settings"` | ||
} | ||
|
||
type Indices map[string]IndexSettings | ||
|
||
var setupLog = ctrl.Log.WithName("setup") | ||
|
||
func DeleteStaleIndices(c *cli.Context) error { | ||
force := c.Bool("force") | ||
deleteList := make([]string, 0) | ||
|
||
var config EsConfig | ||
if err := envconfig.Process(context.Background(), &config); err != nil { | ||
setupLog.Error(err, "unable to parse environment variables") | ||
os.Exit(1) | ||
} | ||
|
||
client, err := elasticsearch.NewClient(elasticsearch.Config{APIKey: config.ApiKey, CloudID: config.CloudId}) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
settings, err := esapi.IndicesGetSettingsRequest{FilterPath: []string{"*.settings.index.creation_date"}}.Do(context.TODO(), client) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
list := Indices{} | ||
|
||
if err := json.NewDecoder(settings.Body).Decode(&list); err != nil { | ||
log.Fatalf("Error parsing the response body: %s", err) | ||
} else { | ||
for k, i := range list { | ||
if strings.Contains(k, "elasticsearch_index") { | ||
now := time.Now().UnixMilli() | ||
created, err := strconv.ParseInt(i.IndexItem.IndexDetail.CreationDate, 10, 64) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using the creation date is a very rudimentary way of identifying stale indices because it does not identify the last time an index was updated. I believe it may be possible to use data from the shards API to determine how 'fresh' an index is based on refresh, write or read metrics. However because content is ephemeral and these are development indices we don't need to be too concerned about destructive requests. |
||
if err != nil { | ||
return err | ||
} | ||
|
||
diffInDays := (now - created) / (1000 * 60 * 60 * 24) | ||
if diffInDays > 30 { | ||
fmt.Printf("The index %+v is %v days old and will be marked for deletion\n", k, diffInDays) | ||
deleteList = append(deleteList, k) | ||
} | ||
} | ||
} | ||
if c := len(deleteList); c > 0 { | ||
if force { | ||
fmt.Println("Deleting indices marked for deletion.") | ||
statusCode, err := deleteIndices(client, deleteList, c) | ||
if err != nil { | ||
return err | ||
} else { | ||
if statusCode == 200 { | ||
fmt.Printf("Deletion request failed. Status code %+v", statusCode) | ||
} else { | ||
fmt.Printf("%+v indices successfully deleted.", c) | ||
} | ||
} | ||
} else { | ||
prompt := promptui.Prompt{ | ||
Label: "Delete indices", | ||
IsConfirm: true, | ||
} | ||
|
||
prompt_result, _ := prompt.Run() | ||
|
||
if prompt_result == "y" { | ||
_, err := deleteIndices(client, deleteList, c) | ||
if err != nil { | ||
return err | ||
} | ||
} else { | ||
fmt.Printf("Operation cancelled.\nThere are %+v indices marked for deletion.\n", c) | ||
} | ||
} | ||
} else { | ||
fmt.Printf("No indices meet the criteria for deletion.") | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func deleteIndices(client *elasticsearch.Client, deleteList []string, c int) (int, error) { | ||
res, err := esapi.IndicesDeleteRequest{Index: deleteList}.Do(context.TODO(), client) | ||
if err != nil { | ||
return res.StatusCode, err | ||
} else { | ||
if res.StatusCode == 200 { | ||
fmt.Printf("Deletion request failed. Status code %+v", res.StatusCode) | ||
return res.StatusCode, errors.New("non 200 status code") | ||
} else { | ||
fmt.Printf("%+v indices successfully deleted.", c) | ||
return res.StatusCode, nil | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this be better as a flag or argument instead of an envvar?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because they're creds I thought it safer to keep them stored as env vars but I suppose we could set them as env vars and reference them in the argument. Am I being too cautious in not allowing a user to expose those vars directly in an arg on the cli (and therefore making it available in their shell history)?