• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

NVIDIA / gpu-operator / 21727069076

05 Feb 2026 08:17PM UTC coverage: 26.122% (+3.2%) from 22.93%
21727069076

push

github

ArangoGutierrez
feat(ci): add weekly forward compatibility testing

Add forward-compatibility.yaml workflow that runs weekly to test the
GPU operator against latest upstream component images (toolkit,
device-plugin, mig-manager). Includes get-latest-images.sh with
retry/backoff for image verification and generate-values-overrides.sh
for Helm values generation.

Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>

3109 of 11902 relevant lines covered (26.12%)

0.3 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.41
/internal/render/render.go
1
/**
2
# Copyright (c) NVIDIA CORPORATION.  All rights reserved.
3
#
4
# Licensed under the Apache License, Version 2.0 (the "License");
5
# you may not use this file except in compliance with the License.
6
# You may obtain a copy of the License at
7
#
8
#     http://www.apache.org/licenses/LICENSE-2.0
9
#
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS,
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
# See the License for the specific language governing permissions and
14
# limitations under the License.
15
**/
16

17
package render
18

19
/*
20
 Render package renders k8s API objects from a given set of template .yaml files
21
 provided in a source directory and a RenderData struct to be used in the rendering process
22

23
 The objects are rendered in `Unstructured` format provided by
24
 k8s.io/apimachinery/pkg/apis/meta/v1/unstructured package.
25
*/
26

27
import (
28
        "bytes"
29
        "fmt"
30
        "io"
31
        "os"
32
        "path"
33
        "strings"
34
        "text/template"
35

36
        "github.com/Masterminds/sprig/v3"
37
        "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
38
        yamlDecoder "k8s.io/apimachinery/pkg/util/yaml"
39
        yamlConverter "sigs.k8s.io/yaml"
40

41
        "github.com/NVIDIA/gpu-operator/internal/utils"
42
)
43

44
const (
45
        maxBufSizeForYamlDecode = 4096
46
)
47

48
var ManifestFileSuffix = []string{"yaml", "yml", "json"}
49

50
// Renderer renders k8s objects from a manifest source dir and TemplatingData used by the templating engine
51
type Renderer interface {
52
        // RenderObjects renders kubernetes objects using provided TemplatingData
53
        RenderObjects(data *TemplatingData) ([]*unstructured.Unstructured, error)
54
}
55

56
// TemplatingData is used by the templating engine to render templates
57
type TemplatingData struct {
58
        // Funcs are additional Functions used during the templating process
59
        Funcs template.FuncMap
60
        // Data used for the rendering process
61
        Data interface{}
62
}
63

64
// NewRenderer creates a Renderer object, that will render all template files provided.
65
// file format needs to be either json or yaml.
66
func NewRenderer(files []string) Renderer {
1✔
67
        return &textTemplateRenderer{
1✔
68
                files: files,
1✔
69
        }
1✔
70
}
1✔
71

72
// textTemplateRenderer is an implementation of the Renderer interface using golang builtin text/template package
73
// as its templating engine
74
type textTemplateRenderer struct {
75
        files []string
76
}
77

78
// RenderObjects renders kubernetes objects utilizing the provided TemplatingData.
79
func (r *textTemplateRenderer) RenderObjects(data *TemplatingData) ([]*unstructured.Unstructured, error) {
1✔
80
        var objs []*unstructured.Unstructured
1✔
81

1✔
82
        for _, file := range r.files {
2✔
83
                out, err := r.renderFile(file, data)
1✔
84
                if err != nil {
2✔
85
                        return nil, fmt.Errorf("error rendering file %s: %w", file, err)
1✔
86
                }
1✔
87
                objs = append(objs, out...)
1✔
88
        }
89
        return objs, nil
1✔
90
}
91

92
// renderFile renders a single file to a list of k8s unstructured objects
93
func (r *textTemplateRenderer) renderFile(filePath string, data *TemplatingData) ([]*unstructured.Unstructured, error) {
1✔
94
        // Read file
1✔
95
        txt, err := os.ReadFile(filePath)
1✔
96
        if err != nil {
2✔
97
                return nil, fmt.Errorf("failed to read manifest file %s: %w", filePath, err)
1✔
98
        }
1✔
99

100
        // Create a new template
101
        tmpl := template.New(path.Base(filePath)).Funcs(sprig.FuncMap()).Option("missingkey=error")
1✔
102

1✔
103
        tmpl.Funcs(template.FuncMap{
1✔
104
                "yaml": func(obj interface{}) (string, error) {
1✔
105
                        yamlBytes, err := yamlConverter.Marshal(obj)
×
106
                        return string(yamlBytes), err
×
107
                },
×
108
                "deref": func(b *bool) bool {
×
109
                        if b == nil {
×
110
                                return false
×
111
                        }
×
112
                        return *b
×
113
                },
114
                "getObjectHash": utils.GetObjectHash,
115
        })
116

117
        if data.Funcs != nil {
1✔
118
                tmpl.Funcs(data.Funcs)
×
119
        }
×
120

121
        if _, err := tmpl.Parse(string(txt)); err != nil {
1✔
122
                return nil, fmt.Errorf("failed to parse manifest file %s: %w", filePath, err)
×
123
        }
×
124
        rendered := bytes.Buffer{}
1✔
125

1✔
126
        if err := tmpl.Execute(&rendered, data.Data); err != nil {
2✔
127
                return nil, fmt.Errorf("failed to render manifest %s: %w", filePath, err)
1✔
128
        }
1✔
129

130
        out := []*unstructured.Unstructured{}
1✔
131

1✔
132
        // special case - if the entire file is whitespace, skip
1✔
133
        if strings.TrimSpace(rendered.String()) == "" {
1✔
134
                return out, nil
×
135
        }
×
136

137
        decoder := yamlDecoder.NewYAMLOrJSONDecoder(&rendered, maxBufSizeForYamlDecode)
1✔
138
        for {
2✔
139
                u := unstructured.Unstructured{}
1✔
140
                if err := decoder.Decode(&u); err != nil {
2✔
141
                        if err == io.EOF {
2✔
142
                                break
1✔
143
                        }
144
                        return nil, fmt.Errorf("failed to unmarshal manifest %s: %w", filePath, err)
1✔
145
                }
146
                // Ensure object is not empty by checking the object kind
147
                if u.GetKind() == "" {
1✔
148
                        continue
×
149
                }
150
                out = append(out, &u)
1✔
151
        }
152

153
        return out, nil
1✔
154
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc