From 1d5cf5b33b17f6c8d4eaab0066cf8716060cfcb7 Mon Sep 17 00:00:00 2001 From: Jose Esparza <28990958+pebeto@users.noreply.github.com> Date: Mon, 8 Apr 2024 23:47:25 -0500 Subject: [PATCH 1/4] Adding `use_ajax` flag to `MLFlow` instances to allow compatibility with both `REST` and `AJAX` endpoints --- src/types/mlflow.jl | 12 +++++++----- src/utils.jl | 3 ++- test/runtests.jl | 1 + test/test_functional.jl | 8 +++++--- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/types/mlflow.jl b/src/types/mlflow.jl index 9ba467b..efd8b3c 100644 --- a/src/types/mlflow.jl +++ b/src/types/mlflow.jl @@ -5,12 +5,14 @@ Base type which defines location and version for MLFlow API service. # Fields - `baseuri::String`: base MLFlow tracking URI, e.g. `http://localhost:5000` -- `apiversion`: used API version, e.g. `2.0` -- `headers`: HTTP headers to be provided with the REST API requests (useful for authetication tokens) +- `apiversion::Union{Integer, AbstractFloat}`: used API version, e.g. `2.0` +- `headers::Dict`: HTTP headers to be provided with the REST API requests (useful for authetication tokens) +- `use_ajax::Bool`: whether to use the AJAX endpoint for the MLFlow service. +Default is `false`, using the REST API endpoint. # Constructors -- `MLFlow(baseuri; apiversion=2.0,headers=Dict())` +- `MLFlow(baseuri; apiversion=2.0,headers=Dict(),use_ajax=false)` - `MLFlow()` - defaults to `MLFlow(ENV["MLFLOW_TRACKING_URI"])` or `MLFlow("http://localhost:5000")` # Examples @@ -29,8 +31,9 @@ struct MLFlow baseuri::String apiversion::Union{Integer, AbstractFloat} headers::Dict + use_ajax::Bool end -MLFlow(baseuri; apiversion=2.0,headers=Dict()) = MLFlow(baseuri, apiversion,headers) +MLFlow(baseuri; apiversion=2.0, headers=Dict(), use_ajax=false) = MLFlow(baseuri, apiversion, headers, use_ajax) function MLFlow() baseuri = "http://localhost:5000" if haskey(ENV, "MLFLOW_TRACKING_URI") @@ -38,5 +41,4 @@ function MLFlow() end return MLFlow(baseuri) end - Base.show(io::IO, t::MLFlow) = show(io, ShowCase(t, [:baseuri,:apiversion], new_lines=true)) diff --git a/src/utils.jl b/src/utils.jl index db29b2b..6bbb91c 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -25,7 +25,8 @@ MLFlowClient.uri(mlf, "experiments/get", Dict(:experiment_id=>10)) ``` """ function uri(mlf::MLFlow, endpoint="", query=missing) - u = URI("$(mlf.baseuri)/ajax-api/$(mlf.apiversion)/mlflow/$(endpoint)") + api_endpoint = mlf.use_ajax ? "ajax-api" : "api" + u = URI("$(mlf.baseuri)/$(api_endpoint)/$(mlf.apiversion)/mlflow/$(endpoint)") !ismissing(query) && return URI(u; query=query) u end diff --git a/test/runtests.jl b/test/runtests.jl index e478e47..e68d247 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,5 +1,6 @@ include("base.jl") +include("test_functional.jl") include("test_experiments.jl") include("test_runs.jl") include("test_loggers.jl") diff --git a/test/test_functional.jl b/test/test_functional.jl index 5534fc1..8d3f748 100644 --- a/test/test_functional.jl +++ b/test/test_functional.jl @@ -35,10 +35,12 @@ end using MLFlowClient: uri, headers using URIs: URI - @test healthcheck(MLFlow()) == true + let baseuri = "http://localhost:5001", apiversion = 2.0, endpoint = "experiments/get" + mlf = MLFlow(baseuri; apiversion=apiversion) + apiuri = uri(mlf, endpoint) + @test apiuri == URI("$baseuri/api/$apiversion/mlflow/$endpoint") - let baseuri = "http://localhost:5001", apiversion = "2.0", endpoint = "experiments/get" - mlf = MLFlow(baseuri; apiversion) + mlf = MLFlow(baseuri; apiversion=apiversion, use_ajax=true) apiuri = uri(mlf, endpoint) @test apiuri == URI("$baseuri/ajax-api/$apiversion/mlflow/$endpoint") end From 77df35c60b46f25298cf9b79e6527646422e9348 Mon Sep 17 00:00:00 2001 From: Jose Esparza <28990958+pebeto@users.noreply.github.com> Date: Fri, 17 May 2024 09:14:20 -0500 Subject: [PATCH 2/4] Removing `use_ajax` in favor of defining API. Moved `baseuri` to `apiroot` --- src/types/mlflow.jl | 18 ++++++++---------- src/utils.jl | 3 +-- test/test_functional.jl | 28 ++++++++++++---------------- 3 files changed, 21 insertions(+), 28 deletions(-) diff --git a/src/types/mlflow.jl b/src/types/mlflow.jl index efd8b3c..2f32a39 100644 --- a/src/types/mlflow.jl +++ b/src/types/mlflow.jl @@ -4,15 +4,14 @@ Base type which defines location and version for MLFlow API service. # Fields -- `baseuri::String`: base MLFlow tracking URI, e.g. `http://localhost:5000` +- `apiroot::String`: API root URL, e.g. `http://localhost:5000/api` - `apiversion::Union{Integer, AbstractFloat}`: used API version, e.g. `2.0` - `headers::Dict`: HTTP headers to be provided with the REST API requests (useful for authetication tokens) -- `use_ajax::Bool`: whether to use the AJAX endpoint for the MLFlow service. Default is `false`, using the REST API endpoint. # Constructors -- `MLFlow(baseuri; apiversion=2.0,headers=Dict(),use_ajax=false)` +- `MLFlow(apiroot; apiversion=2.0,headers=Dict())` - `MLFlow()` - defaults to `MLFlow(ENV["MLFLOW_TRACKING_URI"])` or `MLFlow("http://localhost:5000")` # Examples @@ -28,17 +27,16 @@ mlf = MLFlow(remote_url, headers=Dict("Authorization" => "Bearer 10)) ``` """ function uri(mlf::MLFlow, endpoint="", query=missing) - api_endpoint = mlf.use_ajax ? "ajax-api" : "api" - u = URI("$(mlf.baseuri)/$(api_endpoint)/$(mlf.apiversion)/mlflow/$(endpoint)") + u = URI("$(mlf.apiroot)/$(mlf.apiversion)/mlflow/$(endpoint)") !ismissing(query) && return URI(u; query=query) u end diff --git a/test/test_functional.jl b/test/test_functional.jl index 8d3f748..400ba06 100644 --- a/test/test_functional.jl +++ b/test/test_functional.jl @@ -1,15 +1,15 @@ @testset "MLFlow" begin mlf = MLFlow() - @test mlf.baseuri == ENV["MLFLOW_TRACKING_URI"] + @test mlf.apiroot == ENV["MLFLOW_TRACKING_URI"] @test mlf.apiversion == 2.0 @test mlf.headers == Dict() - mlf = MLFlow("https://localhost:5001", apiversion=3.0) - @test mlf.baseuri == "https://localhost:5001" + mlf = MLFlow("https://localhost:5001/api", apiversion=3.0) + @test mlf.apiroot == "https://localhost:5001/api" @test mlf.apiversion == 3.0 @test mlf.headers == Dict() let custom_headers = Dict("Authorization" => "Bearer EMPTY") - mlf = MLFlow("https://localhost:5001", apiversion=3.0, headers=custom_headers) - @test mlf.baseuri == "https://localhost:5001" + mlf = MLFlow("https://localhost:5001/api", apiversion=3.0, headers=custom_headers) + @test mlf.apiroot == "https://localhost:5001/api" @test mlf.apiversion == 3.0 @test mlf.headers == custom_headers end @@ -21,8 +21,8 @@ end secret_token = "SECRET" custom_headers = Dict("Authorization" => "Bearer $secret_token") - mlf = MLFlow("https://localhost:5001", apiversion=3.0, headers=custom_headers) - @test mlf.baseuri == "https://localhost:5001" + mlf = MLFlow("https://localhost:5001/api", apiversion=3.0, headers=custom_headers) + @test mlf.apiroot == "https://localhost:5001/api" @test mlf.apiversion == 3.0 @test mlf.headers == custom_headers show(io, mlf) @@ -35,19 +35,15 @@ end using MLFlowClient: uri, headers using URIs: URI - let baseuri = "http://localhost:5001", apiversion = 2.0, endpoint = "experiments/get" - mlf = MLFlow(baseuri; apiversion=apiversion) + let apiroot = "http://localhost:5001/api", apiversion = 2.0, endpoint = "experiments/get" + mlf = MLFlow(apiroot; apiversion=apiversion) apiuri = uri(mlf, endpoint) - @test apiuri == URI("$baseuri/api/$apiversion/mlflow/$endpoint") - - mlf = MLFlow(baseuri; apiversion=apiversion, use_ajax=true) - apiuri = uri(mlf, endpoint) - @test apiuri == URI("$baseuri/ajax-api/$apiversion/mlflow/$endpoint") + @test apiuri == URI("$apiroot/$apiversion/mlflow/$endpoint") end - let baseuri = "http://localhost:5001", auth_headers = Dict("Authorization" => "Bearer 123456"), + let apiroot = "http://localhost:5001/api", auth_headers = Dict("Authorization" => "Bearer 123456"), custom_headers = Dict("Content-Type" => "application/json") - mlf = MLFlow(baseuri; headers=auth_headers) + mlf = MLFlow(apiroot; headers=auth_headers) apiheaders = headers(mlf, custom_headers) @test apiheaders == Dict("Authorization" => "Bearer 123456", "Content-Type" => "application/json") end From 66a93594916199cf8d0d1cc42b1d89f0376c57c0 Mon Sep 17 00:00:00 2001 From: Jose Esparza <28990958+pebeto@users.noreply.github.com> Date: Fri, 17 May 2024 09:18:01 -0500 Subject: [PATCH 3/4] Removing `healthcheck` function due to lack of support --- docs/src/reference.md | 1 - src/utils.jl | 16 ---------------- 2 files changed, 17 deletions(-) diff --git a/docs/src/reference.md b/docs/src/reference.md index 656754f..7f79daf 100644 --- a/docs/src/reference.md +++ b/docs/src/reference.md @@ -56,5 +56,4 @@ uri generatefilterfromentity_type generatefilterfromparams generatefilterfromattributes -healthcheck ``` diff --git a/src/utils.jl b/src/utils.jl index 2e6b73e..bc8e225 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -1,19 +1,3 @@ -""" - healthcheck(mlf::MLFlow) - -Checks if MLFlow server is up and running. Returns `true` if it is, `false` -otherwise. -""" -function healthcheck(mlf) - uri = "$(mlf.baseuri)/health" - try - response = HTTP.get(uri) - return String(response.body) == "OK" - catch e - return false - end -end - """ uri(mlf::MLFlow, endpoint="", query=missing) From 839a29cf33c51d4cde357b209cd370c30597d4d1 Mon Sep 17 00:00:00 2001 From: Jose Esparza <28990958+pebeto@users.noreply.github.com> Date: Fri, 17 May 2024 09:37:15 -0500 Subject: [PATCH 4/4] Renaming `MLFLOW_TRACKING_URI` to `MLFLOW_API_URI`, and adding a check to tests --- .github/workflows/CI.yml | 2 +- src/types/mlflow.jl | 6 +++--- test/base.jl | 2 +- test/runtests.jl | 4 ++++ test/test_functional.jl | 2 +- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 234915b..aee1bea 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -50,7 +50,7 @@ jobs: - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 env: - MLFLOW_TRACKING_URI: "http://localhost:5000" + MLFLOW_API_URI: "http://localhost:5000/api" - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v2 with: diff --git a/src/types/mlflow.jl b/src/types/mlflow.jl index 2f32a39..640f8c2 100644 --- a/src/types/mlflow.jl +++ b/src/types/mlflow.jl @@ -12,7 +12,7 @@ Default is `false`, using the REST API endpoint. # Constructors - `MLFlow(apiroot; apiversion=2.0,headers=Dict())` -- `MLFlow()` - defaults to `MLFlow(ENV["MLFLOW_TRACKING_URI"])` or `MLFlow("http://localhost:5000")` +- `MLFlow()` - defaults to `MLFlow(ENV["MLFLOW_API_URI"])` or `MLFlow("http://localhost:5000")` # Examples @@ -34,8 +34,8 @@ end MLFlow(apiroot; apiversion=2.0, headers=Dict()) = MLFlow(apiroot, apiversion, headers) function MLFlow() apiroot = "http://localhost:5000/api" - if haskey(ENV, "MLFLOW_TRACKING_URI") - apiroot = ENV["MLFLOW_TRACKING_URI"] + if haskey(ENV, "MLFLOW_API_URI") + apiroot = ENV["MLFLOW_API_URI"] end return MLFlow(apiroot) end diff --git a/test/base.jl b/test/base.jl index 2561ed0..3fdf83a 100644 --- a/test/base.jl +++ b/test/base.jl @@ -13,7 +13,7 @@ function mlflow_server_is_running(mlf::MLFlow) end # creates an instance of mlf -# skips test if mlflow is not available on default location, ENV["MLFLOW_TRACKING_URI"] +# skips test if mlflow is not available on default location, ENV["MLFLOW_API_URI"] macro ensuremlf() e = quote mlf = MLFlow() diff --git a/test/runtests.jl b/test/runtests.jl index e68d247..401ac17 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,3 +1,7 @@ +if ~haskey(ENV, "MLFLOW_API_URI") + error("WARNING: MLFLOW_API_URI is not set. To run this tests, you need to set the URI of your MLFlow server API") +end + include("base.jl") include("test_functional.jl") diff --git a/test/test_functional.jl b/test/test_functional.jl index 400ba06..0e64fa0 100644 --- a/test/test_functional.jl +++ b/test/test_functional.jl @@ -1,6 +1,6 @@ @testset "MLFlow" begin mlf = MLFlow() - @test mlf.apiroot == ENV["MLFLOW_TRACKING_URI"] + @test mlf.apiroot == ENV["MLFLOW_API_URI"] @test mlf.apiversion == 2.0 @test mlf.headers == Dict() mlf = MLFlow("https://localhost:5001/api", apiversion=3.0)