Skip to content

Commit 27133ce

Browse files
authored
Merge pull request #254 from yashsinghcodes/quick
new health checks and static workflow id
2 parents fad9b50 + 296adee commit 27133ce

File tree

2 files changed

+270
-5
lines changed

2 files changed

+270
-5
lines changed

health.go

Lines changed: 250 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ func deleteJunkOpsWorkflow(ctx context.Context, workflowHealth WorkflowHealth) e
481481

482482
if len(workflows) == 0 {
483483
//log.Printf("[DEBUG] Couldn't find any workflow named SHUFFLE_INTERNAL_OPS_WORKFLOW")
484-
return errors.New("Failed finding workflow named SHUFFLE_INTERNAL_OPS_WORKFLOW")
484+
return errors.New("Failed finding workflow named Ops Dashboard Workflow")
485485
}
486486

487487
//log.Printf("[DEBUG] Found %d workflows named SHUFFLE_INTERNAL_OPS_WORKFLOW: ", len(workflows))
@@ -732,6 +732,7 @@ func RunOpsHealthCheck(resp http.ResponseWriter, request *http.Request) {
732732
log.Printf("[ERROR] Failed running app health check: %s", err)
733733
}
734734

735+
appHealth.Result = ""
735736
openapiAppHealthChannel <- appHealth
736737
errorChannel <- err
737738
}()
@@ -747,9 +748,33 @@ func RunOpsHealthCheck(resp http.ResponseWriter, request *http.Request) {
747748
errorChannel <- err
748749
}()
749750

751+
datastoreHealthChannel := make(chan DatastoreHealth)
752+
go func() {
753+
datastoreHealth, err := RunOpsDatastore(apiKey, orgId)
754+
if err != nil {
755+
log.Printf("[ERROR] Failed running datastore health check: %s", err)
756+
}
757+
758+
datastoreHealthChannel <- datastoreHealth
759+
errorChannel <- err
760+
}()
761+
762+
fileHealthChannel := make(chan FileHealth)
763+
go func () {
764+
fileHealth, err := RunOpsFile(apiKey, orgId)
765+
if err != nil {
766+
log.Printf("[ERROR] Failed running file health check: %s", err)
767+
}
768+
769+
fileHealthChannel <- fileHealth
770+
errorChannel <- err
771+
}()
772+
750773
// Use channel for getting RunOpsWorkflow function results
751774
platformHealth.Apps = <-openapiAppHealthChannel
752775
platformHealth.PythonApps = <-pythonAppHealthChannel
776+
platformHealth.Datastore = <-datastoreHealthChannel
777+
platformHealth.FileOps = <-fileHealthChannel
753778
}
754779

755780
platformHealth.Workflows = <-workflowHealthChannel
@@ -1769,6 +1794,7 @@ func InitOpsWorkflow(apiKey string, OrgId string) (string, error) {
17691794
workflowData.Public = false
17701795
workflowData.Status = ""
17711796
workflowData.Name = "Ops Dashboard Workflow"
1797+
workflowData.ID = "shuffler-doti-ohea-lthc-heckworkflow"
17721798
workflowData.Hidden = true
17731799
workflowData.BackgroundProcessing = true
17741800

@@ -1958,6 +1984,229 @@ func InitOpsWorkflow(apiKey string, OrgId string) (string, error) {
19581984
return workflowData.ID, nil
19591985
}
19601986

1987+
// Create datastore
1988+
// read it
1989+
// delete it
1990+
func RunOpsDatastore(apikey, orgId string) (DatastoreHealth, error) {
1991+
baseUrl := os.Getenv("SHUFFLE_CLOUDRUN_URL")
1992+
if len(baseUrl) == 0 {
1993+
baseUrl = "https://shuffler.io"
1994+
}
1995+
1996+
if project.Environment == "onprem" {
1997+
baseUrl = "http://localhost:5001"
1998+
}
1999+
2000+
datastoreHealth := DatastoreHealth{
2001+
Create: false,
2002+
Read: false,
2003+
Result: "",
2004+
Delete: false,
2005+
}
2006+
2007+
// create datastore entry
2008+
PAYLOAD := `{"key": "SHUFFLE_HEALTH_CHECK", "value": "yesy", "category": "SHUFFLE_HEALTH_CHECK"}`
2009+
url := fmt.Sprintf("%s/api/v1/orgs/%s/set_cache", baseUrl, orgId)
2010+
req, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte(PAYLOAD)))
2011+
if err != nil {
2012+
log.Printf("[ERROR] Failed to create request (%s) for set_cache %s", url, err)
2013+
return datastoreHealth, err
2014+
}
2015+
2016+
req.Header.Set("Authorization", "Bearer "+apikey)
2017+
req.Header.Set("Content-Type", "application/json")
2018+
2019+
// Follow proxy and stuff
2020+
client := GetExternalClient(baseUrl)
2021+
resp, err := client.Do(req)
2022+
resp.Body.Close()
2023+
if err != nil {
2024+
log.Printf("[ERROR] Failed to send request (%s) for set_cache %s", url, err)
2025+
return datastoreHealth, err
2026+
}
2027+
2028+
datastoreHealth.Create = true
2029+
//read datastore entry
2030+
PAYLOAD = fmt.Sprintf(`{"org_id": "%s", "key": "SHUFFLE_HEALTH_CHECK"}`, orgId)
2031+
url = fmt.Sprintf("%s/api/v1/orgs/%s/get_cache", baseUrl, orgId)
2032+
req, err = http.NewRequest("POST", url, bytes.NewBuffer([]byte(PAYLOAD)))
2033+
if err != nil {
2034+
log.Printf("[ERROR] Failed to create request (%s) for get_cache: %s", url, err)
2035+
return datastoreHealth, err
2036+
}
2037+
2038+
req.Header.Set("Authorization", "Bearer "+apikey)
2039+
req.Header.Set("Content-Type", "application/json")
2040+
2041+
resp, err = client.Do(req)
2042+
if err != nil {
2043+
log.Printf("[ERROR] Failed to send request to get_cache: %s", err)
2044+
return datastoreHealth, err
2045+
}
2046+
2047+
dataStoreValue, err := io.ReadAll(resp.Body)
2048+
if err != nil {
2049+
log.Printf("[ERROR] Failed to read datastore return value: %s", err)
2050+
}
2051+
2052+
datastoreHealth.Result = string(dataStoreValue)
2053+
resp.Body.Close()
2054+
datastoreHealth.Read = true
2055+
2056+
// Delete
2057+
PAYLOAD = fmt.Sprintf(`{"org_id": "%s", "key": "SHUFFLE_HEALTH_CHECK"}`, orgId)
2058+
url = fmt.Sprintf("%s/api/v1/orgs/%s/delete_cache", baseUrl, orgId)
2059+
req, err = http.NewRequest("POST", url, bytes.NewBuffer([]byte(PAYLOAD)))
2060+
if err != nil {
2061+
log.Printf("[ERROR] Failed to create request (%s) for delete_key: %s", url, err)
2062+
return datastoreHealth, err
2063+
}
2064+
2065+
req.Header.Set("Authorization", "Bearer "+apikey)
2066+
req.Header.Set("Content-Type", "application/json")
2067+
2068+
resp, err = client.Do(req)
2069+
if err != nil {
2070+
log.Printf("[ERROR] Failed to send request to delete_key: %s", err)
2071+
return datastoreHealth, err
2072+
}
2073+
2074+
datastoreHealth.Delete = true
2075+
return datastoreHealth, nil
2076+
}
2077+
2078+
func RunOpsFile(apikey, orgId string) (FileHealth, error) {
2079+
baseUrl := os.Getenv("SHUFFLE_CLOUDRUN_URL")
2080+
if len(baseUrl) == 0 {
2081+
baseUrl = "https://shuffler.io"
2082+
}
2083+
2084+
if project.Environment == "onprem" {
2085+
baseUrl = "http://localhost:5001"
2086+
}
2087+
2088+
fileHealth := FileHealth{
2089+
Create: false,
2090+
FileId: "",
2091+
Upload: false,
2092+
Delete: false,
2093+
}
2094+
2095+
PAYLOAD := fmt.Sprintf(`{"filename": "SHUFFLE_HEALTH_TEST_FILE", "org_id": "%s", "workflow_id": "global"}`, orgId)
2096+
url := fmt.Sprintf("%s/api/v1/files/create", baseUrl)
2097+
2098+
req, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte(PAYLOAD)))
2099+
if err != nil {
2100+
log.Printf("[ERROR] Failed to create new request for create file(%s): %s", url, err)
2101+
return fileHealth, err
2102+
}
2103+
2104+
req.Header.Set("Authorization", "Bearer "+apikey)
2105+
req.Header.Set("Content-Type", "application/json")
2106+
2107+
var fileRespStruct struct {
2108+
Success bool `json:success`
2109+
Id string `json:id`
2110+
}
2111+
2112+
client := GetExternalClient(baseUrl)
2113+
resp, err := client.Do(req)
2114+
defer resp.Body.Close()
2115+
if err != nil {
2116+
log.Printf("[ERROR] Failed to send request (%s) for set_cache %s", url, err)
2117+
return fileHealth, err
2118+
}
2119+
2120+
body, err := io.ReadAll(resp.Body)
2121+
if err != nil {
2122+
log.Printf("[ERROR] Failed to read response body")
2123+
return fileHealth, err
2124+
}
2125+
2126+
2127+
err = json.Unmarshal(body, &fileRespStruct)
2128+
if err != nil {
2129+
log.Printf("[ERROR] Failed to unmarshal response")
2130+
return fileHealth, err
2131+
}
2132+
2133+
fileHealth.Create = true
2134+
//Upload file
2135+
url = fmt.Sprintf("%s/api/v1/files/%s/upload", baseUrl, fileRespStruct.Id)
2136+
remoteUrl := "https://raw.githubusercontent.com/Shuffle/Shuffle/refs/heads/main/LICENSE"
2137+
2138+
resp, err = http.Get(remoteUrl)
2139+
if err != nil {
2140+
log.Printf("[ERROR] Failed to fetch remote file: %s", err)
2141+
return fileHealth, err
2142+
}
2143+
2144+
defer resp.Body.Close()
2145+
2146+
var buf bytes.Buffer
2147+
w := multipart.NewWriter(&buf)
2148+
formFile, err := w.CreateFormFile("shuffle_file", "file.txt")
2149+
if err != nil {
2150+
log.Printf("[ERROR] Failed to create form file: %s", err)
2151+
return fileHealth, err
2152+
}
2153+
2154+
if _, err := io.Copy(formFile, resp.Body); err != nil {
2155+
log.Printf("[ERROR] Failed to copy remote file to form: %s", err)
2156+
return fileHealth, err
2157+
}
2158+
2159+
w.Close()
2160+
req, err = http.NewRequest("POST", url, &buf)
2161+
if err != nil {
2162+
log.Printf("[ERROR] Failed to create upload request: %s", err)
2163+
return fileHealth, err
2164+
}
2165+
2166+
req.Header.Set("Authorization", "Bearer "+apikey)
2167+
req.Header.Set("Content-Type", w.FormDataContentType())
2168+
uploadResp, err := client.Do(req)
2169+
if err != nil {
2170+
log.Printf("[ERROR] Upload request failed: %s", err)
2171+
return fileHealth, err
2172+
}
2173+
2174+
defer uploadResp.Body.Close()
2175+
if uploadResp.StatusCode != 200 {
2176+
log.Printf("[ERROR] Failed to upload file, not 200 status code")
2177+
return fileHealth, fmt.Errorf("upload failed for file")
2178+
}
2179+
2180+
log.Printf("[INFO] Filed uploaded successfully to %s", url)
2181+
fileHealth.FileId = fileRespStruct.Id
2182+
fileHealth.Upload = true
2183+
//Delete file
2184+
url = fmt.Sprintf("%s/api/v1/files/%s?remove_metadata=true", baseUrl, fileRespStruct.Id)
2185+
req, err = http.NewRequest("DELETE", url, nil)
2186+
if err != nil {
2187+
log.Printf("[ERROR] Failed to create delete request: %s", err)
2188+
return fileHealth, err
2189+
}
2190+
2191+
req.Header.Set("Authorization", "Bearer "+apikey)
2192+
resp, err = client.Do(req)
2193+
if err != nil {
2194+
log.Printf("[ERROR] Failed to send delete request: %s", err)
2195+
return fileHealth, err
2196+
}
2197+
defer resp.Body.Close()
2198+
2199+
if resp.StatusCode != 200 {
2200+
log.Printf("[ERROR] Failed to delete file, not 200 status code")
2201+
return fileHealth, fmt.Errorf("delete failed for file")
2202+
}
2203+
2204+
log.Printf("[INFO] File %s deleted successfully with metadata.", fileRespStruct.Id)
2205+
fileHealth.Delete = true
2206+
2207+
return fileHealth, nil
2208+
}
2209+
19612210
func GetStaticWorkflowHealth(ctx context.Context, workflow Workflow) (Workflow, []string, error) {
19622211
orgUpdated := false
19632212
startnodeFound := false

structs.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,9 +1640,9 @@ type Notification struct {
16401640
Personal bool `json:"personal" datastore:"personal"`
16411641
Read bool `json:"read" datastore:"read"`
16421642

1643-
ModifiedBy string `json:"modified_by" datastore:"modified_by"`
1644-
Ignored bool `json:"ignored" datastore:"ignored"`
1645-
ExecutionId string `json:"execution_id" datastore:"execution_id"`
1643+
ModifiedBy string `json:"modified_by" datastore:"modified_by"`
1644+
Ignored bool `json:"ignored" datastore:"ignored"`
1645+
ExecutionId string `json:"execution_id" datastore:"execution_id"`
16461646
}
16471647

16481648
type NotificationCached struct {
@@ -4291,6 +4291,20 @@ type AppHealth struct {
42914291
ExecutionID string `json:"execution_id"`
42924292
}
42934293

4294+
type DatastoreHealth struct {
4295+
Create bool `json:"create"`
4296+
Read bool `json:"read"`
4297+
Result string `json:"result"`
4298+
Delete bool `json:"delete"`
4299+
}
4300+
4301+
type FileHealth struct {
4302+
Create bool `json:"create"`
4303+
FileId string `json:"fileId"`
4304+
Upload bool `json:"get_file"`
4305+
Delete bool `json:"delete"`
4306+
}
4307+
42944308
type WorkflowHealth struct {
42954309
Create bool `json:"create"`
42964310
Run bool `json:"run"`
@@ -4326,7 +4340,9 @@ type HealthCheck struct {
43264340
Updated int64 `json:"updated"`
43274341
Apps AppHealth `json:"apps"`
43284342
Workflows WorkflowHealth `json:"workflows"`
4329-
PythonApps AppHealth `json:"python_apps"`
4343+
PythonApps AppHealth `json:"python_apps"`
4344+
Datastore DatastoreHealth `json:"datastore"`
4345+
FileOps FileHealth `json:"fileops"`
43304346
}
43314347

43324348
type HealthCheckDB struct {

0 commit comments

Comments
 (0)