[ui] Jobspec UI block: Descriptions and Links (#18292)

* Hacky but shows links and desc

* markdown

* Small pre-test cleanup

* Test for UI description and link rendering

* JSON jobspec docs and variable example job get UI block

* Jobspec documentation for UI block

* Description and links moved into the Title component and made into Helios components

* Marked version upgrade

* Allow links without a description and max description to 1000 chars

* Node 18 for setup-js

* markdown sanitization

* Ui to UI and docs change

* Canonicalize, copy and diff for job.ui

* UI block added to testJob for structs testing

* diff test

* Remove redundant reset

* For readability, changing the receiving pointer of copied job variables

* TestUI endpiont conversion tests

* -require +must

* Nil check on Links

* JobUIConfig.Links as pointer

---------

Co-authored-by: Tim Gross <tgross@hashicorp.com>
This commit is contained in:
Phil Renaud
2024-05-22 15:00:45 -04:00
committed by GitHub
parent 09bd11383c
commit e8b77fcfa0
22 changed files with 2109 additions and 1310 deletions

View File

@@ -1039,6 +1039,7 @@ func ApiJobToStructJob(job *api.Job) *structs.Job {
VaultNamespace: *job.VaultNamespace,
Constraints: ApiConstraintsToStructs(job.Constraints),
Affinities: ApiAffinitiesToStructs(job.Affinities),
UI: ApiJobUIConfigToStructs(job.UI),
}
// Update has been pushed into the task groups. stagger and max_parallel are
@@ -2087,6 +2088,30 @@ func ApiAffinitiesToStructs(in []*api.Affinity) []*structs.Affinity {
return out
}
func ApiJobUIConfigToStructs(jobUI *api.JobUIConfig) *structs.JobUIConfig {
if jobUI == nil {
return nil
}
var links []*structs.JobUILink
if len(jobUI.Links) > 0 {
links = make([]*structs.JobUILink, len(jobUI.Links))
for i, link := range jobUI.Links {
links[i] = &structs.JobUILink{
Label: link.Label,
Url: link.URL,
}
}
} else {
links = nil
}
return &structs.JobUIConfig{
Description: jobUI.Description,
Links: links,
}
}
func ApiAffinityToStructs(a1 *api.Affinity) *structs.Affinity {
return &structs.Affinity{
LTarget: a1.LTarget,

View File

@@ -4396,3 +4396,51 @@ func Test_apiWorkloadIdentityToStructs(t *testing.T) {
TTL: 2 * time.Hour,
}))
}
func TestConversion_ApiJobUIConfigToStructs(t *testing.T) {
t.Run("nil jobUI", func(t *testing.T) {
must.Nil(t, ApiJobUIConfigToStructs(nil))
})
t.Run("empty jobUI", func(t *testing.T) {
jobUI := &api.JobUIConfig{}
expected := &structs.JobUIConfig{
Description: "",
Links: nil,
}
result := ApiJobUIConfigToStructs(jobUI)
must.Eq(t, expected, result)
})
t.Run("jobUI with empty description and links", func(t *testing.T) {
jobUI := &api.JobUIConfig{
Description: "",
Links: []*api.JobUILink{},
}
expected := &structs.JobUIConfig{
Description: "",
Links: nil,
}
result := ApiJobUIConfigToStructs(jobUI)
must.Eq(t, expected, result)
})
t.Run("jobUI with links", func(t *testing.T) {
jobUI := &api.JobUIConfig{
Description: "Test description",
Links: []*api.JobUILink{
{Label: "Link 1", URL: "http://example.com/1"},
{Label: "Link 2", URL: "http://example.com/2"},
},
}
expected := &structs.JobUIConfig{
Description: "Test description",
Links: []*structs.JobUILink{
{Label: "Link 1", Url: "http://example.com/1"},
{Label: "Link 2", Url: "http://example.com/2"},
},
}
result := ApiJobUIConfigToStructs(jobUI)
must.Eq(t, expected, result)
})
}