-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add functioning / barebones version of the app
- Loading branch information
1 parent
55946e4
commit de7ce9b
Showing
20 changed files
with
1,070 additions
and
14 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,184 @@ | ||
box::use( | ||
httr2[ | ||
request, | ||
req_auth_bearer_token, | ||
req_dry_run, | ||
req_perform, | ||
resp_body_string, | ||
req_user_agent | ||
], | ||
magrittr[`%>%`], | ||
jsonlite[fromJSON], | ||
dplyr[filter], | ||
glue[glue] | ||
) | ||
|
||
#' Simple function to get the access token from environment | ||
#' @return Character token, if present | ||
get_access_token <- function() { | ||
token <- Sys.getenv( | ||
"CONNECT_API_KEY", | ||
unset = "NO_TOKEN" | ||
) | ||
if (token == "NO_TOKEN" || token == "") { | ||
stop("Are you sure your CONNECT_API_KEY is set?") | ||
} else { | ||
token | ||
} | ||
} | ||
|
||
#' Simple function to make an API url | ||
#' @param host Character. Default CONNECT_SERVER set as an envvar | ||
#' @param endpoint Character. Default is "content" | ||
#' @param versioned Logical. Whether to use versioned API. Default is FALSE | ||
#' @return url for the API | ||
get_api_url <- function( | ||
host = Sys.getenv("CONNECT_SERVER"), | ||
endpoint = "content", | ||
version = "v1" | ||
) { | ||
glue("{host}__api__/{version}/{endpoint}/") | ||
} | ||
|
||
#' Function to get a list of all apps belonging to the token | ||
#' | ||
#' @param app_mode_filter Character. The filter for app_mode in the API | ||
#' response. Default is "shiny". | ||
#' @param url Character. The URL for API endpoint | ||
#' @param dry_run Logical. Whether to dry run the API for debugging. | ||
#' Default is FALSE | ||
#' @export | ||
get_app_list <- function( | ||
app_mode_filter = "shiny", | ||
endpoint = "content", | ||
dry_run = FALSE | ||
) { | ||
|
||
url <- get_api_url( | ||
endpoint = endpoint | ||
) | ||
|
||
api_request <- request(url) %>% | ||
req_user_agent("LogAnalyzer") %>% | ||
req_auth_bearer_token(get_access_token()) | ||
|
||
if (dry_run) { | ||
api_request %>% | ||
req_dry_run() | ||
} else { | ||
api_request %>% | ||
req_perform() %>% | ||
resp_body_string() %>% | ||
fromJSON() %>% | ||
filter(app_mode == app_mode_filter) | ||
} | ||
} | ||
|
||
#' Function to get a list of all jobs for a specific app | ||
#' | ||
#' @param guid Character. The guid for the app in question | ||
#' @param url Character. The URL for API endpoint | ||
#' @param dry_run Logical. Whether to dry run the API for debugging. | ||
#' Default is FALSE | ||
#' @export | ||
get_job_list <- function( | ||
guid = NULL, | ||
endpoint = "content", | ||
dry_run = FALSE | ||
) { | ||
|
||
url <- get_api_url( | ||
endpoint = endpoint | ||
) | ||
|
||
api_request <- request( | ||
glue("{url}{guid}/jobs") | ||
) %>% | ||
req_user_agent("LogAnalyzer") %>% | ||
req_auth_bearer_token(get_access_token()) | ||
|
||
if (dry_run) { | ||
api_request %>% | ||
req_dry_run() | ||
} else { | ||
api_request %>% | ||
req_perform() %>% | ||
resp_body_string() %>% | ||
fromJSON() | ||
} | ||
} | ||
|
||
#' Function to get a list of all logs for a job for a specific app | ||
#' | ||
#' @param guid Character. The guid for the app in question | ||
#' @param job_key Character. The key for the job in question | ||
#' @param url Character. The URL for API endpoint | ||
#' @param tail Logical. Whether to show the tail only for the logs | ||
#' @param dry_run Logical. Whether to dry run the API for debugging. | ||
#' Default is FALSE | ||
#' @export | ||
get_job_logs <- function( | ||
guid = NULL, | ||
job_key = NULL, | ||
endpoint = "content", | ||
tail = FALSE, | ||
dry_run = FALSE | ||
) { | ||
|
||
url <- get_api_url( | ||
endpoint = endpoint | ||
) | ||
|
||
api_request <- request( | ||
glue("{url}{guid}/jobs/{job_key}/{ifelse(tail, 'tail', 'log')}") | ||
) %>% | ||
req_user_agent("LogAnalyzer") %>% | ||
req_auth_bearer_token(get_access_token()) | ||
|
||
if (dry_run) { | ||
api_request %>% | ||
req_dry_run() | ||
} else { | ||
logs <- api_request %>% | ||
req_perform() %>% | ||
resp_body_string() %>% | ||
fromJSON() | ||
logs["entries"] %>% | ||
data.frame() | ||
} | ||
} | ||
|
||
#' Function to download the logfile for a specific app | ||
#' | ||
#' @param guid Character. The guid for the app in question | ||
#' @param job_key Character. The key for the job in quesrtion | ||
#' @param url Character. The URL for API endpoint | ||
#' @param dry_run Logical. Whether to dry run the API for debugging. | ||
#' Default is FALSE | ||
#' @export | ||
download_job_logs <- function( | ||
guid = NULL, | ||
job_key = NULL, | ||
endpoint = "content", | ||
dry_run = FALSE | ||
) { | ||
|
||
url <- get_api_url( | ||
endpoint = endpoint | ||
) | ||
|
||
api_request <- request( | ||
glue("{url}{guid}/jobs/{job_key}/download") | ||
) %>% | ||
req_user_agent("LogAnalyzer") %>% | ||
req_auth_bearer_token(get_access_token()) | ||
|
||
if (dry_run) { | ||
api_request %>% | ||
req_dry_run() | ||
} else { | ||
api_request %>% | ||
req_perform() %>% | ||
resp_body_string() | ||
} | ||
} |
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,55 @@ | ||
box::use( | ||
shiny[ | ||
div, | ||
span, | ||
icon, | ||
a, | ||
strong | ||
], | ||
glue[glue] | ||
) | ||
|
||
box::use( | ||
app/logic/general_utils[format_timestamp] | ||
) | ||
|
||
#' Function to process each row for the app table | ||
#' This creates the HTML for the row | ||
#' | ||
#' @export | ||
process_app_data <- function( | ||
app_data | ||
) { | ||
app_info <- strsplit(app_data, "_-_")[[1]] | ||
div( | ||
class = "app-entry", | ||
div( | ||
class = "app-title", | ||
span( | ||
app_info[1], | ||
a( | ||
href = app_info[3], | ||
class = "app-link", | ||
icon( | ||
name = "arrow-up-right-from-square", | ||
class = "app-link-icon" | ||
), | ||
target = "_blank" | ||
) | ||
) | ||
), | ||
div( | ||
class = "app-metadata", | ||
div( | ||
class = "app-last-deployed", | ||
strong("Last Deployed: "), | ||
format_timestamp(app_info[4]) | ||
), | ||
span( | ||
class = "app-r-version", | ||
strong("R version: "), | ||
app_info[2] | ||
) | ||
) | ||
) | ||
} |
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,39 @@ | ||
#' Function to check if a string of log text has error keywords | ||
#' | ||
#' @param text Character. The log string | ||
#' @param wordlist Character vector. List of keywords to scan. Default | ||
#' list is `c("halt", "err", "terminat", "not found")` | ||
#' @param ignore_case Logical. Whether to ignore the case for words | ||
#' Default is TRUE | ||
#' @export | ||
check_text_error <- function( | ||
text, | ||
wordlist = c("halt", "err", "terminat", "not found"), | ||
ignore_case = TRUE | ||
) { | ||
grepl( | ||
paste(wordlist, collapse = "|"), | ||
text, | ||
ignore.case = ignore_case | ||
) | ||
} | ||
|
||
#' Function to convert timestamp between formats | ||
#' | ||
#' @param timestamp Character. The timestamp string | ||
#' @param from Character. Original format. Default is "%Y-%m-%dT%H:%M:%OSZ" | ||
#' @param to Character. New format. Default is "%Y-%m-%d %H:%M:%S" | ||
#' @export | ||
format_timestamp <- function( | ||
timestamp, | ||
from = "%Y-%m-%dT%H:%M:%OSZ", | ||
to = "%Y-%m-%d %H:%M:%S" | ||
) { | ||
format( | ||
as.POSIXct( | ||
timestamp, | ||
format = from | ||
), | ||
format = to | ||
) | ||
} |
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,47 @@ | ||
box::use( | ||
shiny[ | ||
div, | ||
span, | ||
icon, | ||
a, | ||
strong | ||
], | ||
glue[glue] | ||
) | ||
|
||
box::use( | ||
app/logic/general_utils[format_timestamp] | ||
) | ||
|
||
|
||
#' Function to process each row for the job table | ||
#' This creates the HTML for the row | ||
#' | ||
#' @export | ||
process_job_data <- function( | ||
job_data | ||
) { | ||
job_info <- strsplit(job_data, "_-_")[[1]] | ||
div( | ||
class = "job-entry", | ||
div( | ||
class = "job-id", | ||
job_info[1] | ||
), | ||
div( | ||
class = "job-key", | ||
strong("Key: "), | ||
job_info[2] | ||
), | ||
div( | ||
class = "job-start-time", | ||
strong("Start: "), | ||
format_timestamp(job_info[3], "%Y-%m-%dT%H:%M:%S") | ||
), | ||
div( | ||
class = "job-end-time", | ||
strong("End: "), | ||
format_timestamp(job_info[4], "%Y-%m-%dT%H:%M:%S") | ||
) | ||
) | ||
} |
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,55 @@ | ||
box::use( | ||
glue[glue], | ||
shiny[ | ||
icon, | ||
div | ||
] | ||
) | ||
|
||
box::use( | ||
app/logic/general_utils[check_text_error, format_timestamp] | ||
) | ||
|
||
#' Function to process each row for the log table | ||
#' This creates the HTML for the row | ||
#' | ||
#' @export | ||
process_log_data <- function( | ||
log_data | ||
) { | ||
log_info <- strsplit(log_data, "_-_")[[1]] | ||
status <- get_status_info(log_info[1], log_info[3]) | ||
div( | ||
class = glue("log-entry {status[1]}-highlight"), | ||
icon( | ||
name = status[2], | ||
class = glue( | ||
"log-status {status[1]}-text fa-solid" | ||
), | ||
), | ||
div( | ||
class = "log-info-block", | ||
div( | ||
class = glue("log-info {status[1]}-text"), | ||
log_info[3] | ||
), | ||
div( | ||
class = "log-time", | ||
format_timestamp(log_info[2]) | ||
) | ||
) | ||
) | ||
} | ||
|
||
get_status_info <- function( | ||
output_type, | ||
log_data | ||
) { | ||
if (output_type == "stdout") { | ||
c("green", "circle-info") | ||
} else if (output_type == "stderr" && check_text_error(log_data)) { | ||
c("red", "circle-xmark") | ||
} else { | ||
c("yellow", "circle-info") | ||
} | ||
} |
Oops, something went wrong.