Skip to content

Commit 674a18b

Browse files
authored
Merge pull request #63 from dpc-sdp/feature/add-facts-to-metadata-output
Added facts to project-metadata output
2 parents 5b94a71 + 816f923 commit 674a18b

2 files changed

Lines changed: 150 additions & 16 deletions

File tree

cmd/project-metadata/metadata.go

Lines changed: 146 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,35 @@ type Response struct {
2121
}
2222

2323
type ProjectMetadata struct {
24-
ProjectName string `json:"project"`
25-
Type string `json:"type"`
26-
Maintainer string `json:"maintainer"`
27-
SectionIoApplication string `json:"section-io-application"`
28-
ApexDomain string `json:"apex-domain"`
29-
BackendProject string `json:"backend-project"`
30-
ProductionDomain string `json:"production-domain"`
24+
ProjectName string `json:"project"`
25+
Type string `json:"type"`
26+
Maintainer string `json:"maintainer"`
27+
SectionIoApplication string `json:"section-io-application"`
28+
ApexDomain string `json:"apex-domain"`
29+
BackendProject string `json:"backend-project"`
30+
ProductionDomain string `json:"production-domain"`
31+
Facts map[string]string `json:"facts,omitempty"`
32+
}
33+
34+
// Fact represents a single fact from the Lagoon API
35+
type Fact struct {
36+
Name string `json:"name"`
37+
Value string `json:"value"`
38+
Description string `json:"description"`
39+
}
40+
41+
// Environment represents an environment with facts
42+
type Environment struct {
43+
Name string `json:"name"`
44+
Facts []Fact `json:"facts"`
45+
}
46+
47+
// ProjectByNameResponse represents the response from the ProjectByName query
48+
type ProjectByNameResponse struct {
49+
ProjectByName struct {
50+
Name string `json:"name"`
51+
Environments []Environment `json:"environments"`
52+
} `json:"projectByName"`
3153
}
3254

3355
// parseTypes parses a comma-separated string of types and returns a slice of types
@@ -87,6 +109,7 @@ func Metadata(ctx context.Context, c *cli.Command) error {
87109

88110
all := c.Bool("all")
89111
metadataType := c.String("type")
112+
includeFacts := c.Bool("include-facts")
90113
args := make([]string, 0)
91114

92115
// Parse the type parameter to handle comma-separated values
@@ -124,6 +147,13 @@ func Metadata(ctx context.Context, c *cli.Command) error {
124147
return err
125148
}
126149

150+
// Get extended project info to access productionEnvironment field
151+
extendedProject := &schema.Project{}
152+
err = client.ProjectByNameExtended(ctx, v, extendedProject)
153+
if err != nil {
154+
return err
155+
}
156+
127157
item := ProjectMetadata{
128158
ProjectName: project.Name,
129159
Type: project.Metadata["type"],
@@ -134,6 +164,75 @@ func Metadata(ctx context.Context, c *cli.Command) error {
134164
ProductionDomain: project.Metadata["production-domain"],
135165
}
136166

167+
// Fetch facts if requested
168+
if includeFacts {
169+
facts := make(map[string]string)
170+
171+
// Use the specific GraphQL query to fetch facts from production environment
172+
query := `
173+
query ProjectByName(
174+
$name: String!
175+
$type: EnvType
176+
$keyFacts: Boolean
177+
$summary: Boolean
178+
) {
179+
projectByName(name: $name) {
180+
name
181+
environments(type: $type) {
182+
name
183+
facts(keyFacts: $keyFacts, summary: $summary) {
184+
name
185+
value
186+
description
187+
}
188+
}
189+
}
190+
}
191+
`
192+
193+
variables := map[string]interface{}{
194+
"name": project.Name,
195+
"type": "PRODUCTION",
196+
"keyFacts": true,
197+
"summary": false,
198+
}
199+
200+
response, err := client.ProcessRaw(ctx, query, variables)
201+
if err != nil {
202+
facts["status"] = fmt.Sprintf("Unable to fetch facts: %v", err)
203+
} else {
204+
// Parse the response
205+
responseBytes, err := json.Marshal(response)
206+
if err != nil {
207+
facts["status"] = fmt.Sprintf("Unable to marshal response: %v", err)
208+
} else {
209+
var projectResponse ProjectByNameResponse
210+
err = json.Unmarshal(responseBytes, &projectResponse)
211+
if err != nil {
212+
facts["status"] = fmt.Sprintf("Unable to parse response: %v", err)
213+
} else {
214+
// Extract facts from production environments
215+
if len(projectResponse.ProjectByName.Environments) > 0 {
216+
for _, env := range projectResponse.ProjectByName.Environments {
217+
for _, fact := range env.Facts {
218+
if fact.Name != "" && fact.Value != "" {
219+
facts[fact.Name] = fact.Value
220+
}
221+
}
222+
}
223+
if len(facts) == 0 {
224+
facts["status"] = "No facts available for production environment"
225+
}
226+
} else {
227+
facts["status"] = "No production environment found"
228+
}
229+
}
230+
}
231+
}
232+
233+
item.Facts = facts
234+
}
235+
137236
output.Items = append(output.Items, item)
138237
}
139238

@@ -154,6 +253,9 @@ func Metadata(ctx context.Context, c *cli.Command) error {
154253
"Backend Project",
155254
"Production Domain",
156255
}
256+
if includeFacts {
257+
header = append(header, "Facts")
258+
}
157259
writer.Write(header)
158260

159261
// Write CSV data rows
@@ -167,21 +269,37 @@ func Metadata(ctx context.Context, c *cli.Command) error {
167269
item.BackendProject,
168270
item.ProductionDomain,
169271
}
272+
if includeFacts {
273+
factsStr := ""
274+
if item.Facts != nil {
275+
for key, value := range item.Facts {
276+
if factsStr != "" {
277+
factsStr += "; "
278+
}
279+
factsStr += fmt.Sprintf("%s: %s", key, value)
280+
}
281+
}
282+
record = append(record, factsStr)
283+
}
170284
writer.Write(record)
171285
}
172286
} else {
173287
table := simpletable.New()
174288

289+
headerCells := []*simpletable.Cell{
290+
{Align: simpletable.AlignLeft, Text: "Project"},
291+
{Align: simpletable.AlignLeft, Text: "Type"},
292+
{Align: simpletable.AlignLeft, Text: "Maintainer"},
293+
{Align: simpletable.AlignLeft, Text: "SectionIO App"},
294+
{Align: simpletable.AlignLeft, Text: "Apex Domain"},
295+
{Align: simpletable.AlignLeft, Text: "Backend Project"},
296+
{Align: simpletable.AlignLeft, Text: "Production Domain"},
297+
}
298+
if includeFacts {
299+
headerCells = append(headerCells, &simpletable.Cell{Align: simpletable.AlignLeft, Text: "Facts"})
300+
}
175301
table.Header = &simpletable.Header{
176-
Cells: []*simpletable.Cell{
177-
{Align: simpletable.AlignLeft, Text: "Project"},
178-
{Align: simpletable.AlignLeft, Text: "Type"},
179-
{Align: simpletable.AlignLeft, Text: "Maintainer"},
180-
{Align: simpletable.AlignLeft, Text: "SectionIO App"},
181-
{Align: simpletable.AlignLeft, Text: "Apex Domain"},
182-
{Align: simpletable.AlignLeft, Text: "Backend Project"},
183-
{Align: simpletable.AlignLeft, Text: "Production Domain"},
184-
},
302+
Cells: headerCells,
185303
}
186304

187305
for _, item := range output.Items {
@@ -194,6 +312,18 @@ func Metadata(ctx context.Context, c *cli.Command) error {
194312
{Text: item.BackendProject},
195313
{Text: item.ProductionDomain},
196314
}
315+
if includeFacts {
316+
factsStr := ""
317+
if item.Facts != nil {
318+
for key, value := range item.Facts {
319+
if factsStr != "" {
320+
factsStr += "\n"
321+
}
322+
factsStr += fmt.Sprintf("%s: %s", key, value)
323+
}
324+
}
325+
r = append(r, &simpletable.Cell{Text: factsStr})
326+
}
197327
table.Body.Cells = append(table.Body.Cells, r)
198328
}
199329
table.SetStyle(simpletable.StyleCompactLite)

main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ func main() {
111111
DefaultText: "all",
112112
Value: "all",
113113
},
114+
&cli.BoolFlag{
115+
Name: "include-facts",
116+
Usage: "Include project facts (base image, Drupal version, etc.)",
117+
},
114118
&cli.StringFlag{
115119
Name: "output",
116120
Usage: "Output format - supports json, table, csv",

0 commit comments

Comments
 (0)