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

tensorchord / envd / 18149755418

01 Oct 2025 02:45AM UTC coverage: 42.475% (-0.3%) from 42.787%
18149755418

push

github

web-flow
chore(deps): bump github.com/go-viper/mapstructure/v2 from 2.3.0 to 2.4.0 (#2034)

chore(deps): bump github.com/go-viper/mapstructure/v2

Bumps [github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure) from 2.3.0 to 2.4.0.
- [Release notes](https://github.com/go-viper/mapstructure/releases)
- [Changelog](https://github.com/go-viper/mapstructure/blob/main/CHANGELOG.md)
- [Commits](https://github.com/go-viper/mapstructure/compare/v2.3.0...v2.4.0)

---
updated-dependencies:
- dependency-name: github.com/go-viper/mapstructure/v2
  dependency-version: 2.4.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

5182 of 12200 relevant lines covered (42.48%)

165.16 hits per line

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

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

15
package types
16

17
import (
18
        "encoding/json"
19
        "fmt"
20

21
        "github.com/cockroachdb/errors"
22
        "github.com/docker/docker/api/types/container"
23
        "github.com/docker/docker/api/types/image"
24
        dockersystem "github.com/docker/docker/api/types/system"
25
        "github.com/moby/buildkit/util/system"
26
        servertypes "github.com/tensorchord/envd-server/api/types"
27

28
        "github.com/tensorchord/envd/pkg/util/netutil"
29
        "github.com/tensorchord/envd/pkg/version"
30
)
31

32
const (
33
        // environment PATH
34
        DefaultSystemPath = system.DefaultPathEnvUnix
35
        DefaultCondaPath  = "/opt/conda/envs/envd/bin:/opt/conda/bin:/home/envd/.local/bin"
36
        DefaultJuliaPath  = "/usr/local/julia/bin"
37
        // image
38
        PythonBaseImage   = "ubuntu:22.04"
39
        EnvdStarshipImage = "tensorchord/starship:v0.0.1"
40
        // supervisor
41
        HorustImage      = "tensorchord/horust:v0.2.3"
42
        HorustServiceDir = "/etc/horust/services"
43
        HorustLogDir     = "/var/log/horust"
44
        // env
45
        EnvdWorkDir = "ENVD_WORKDIR"
46
)
47

48
var EnvdSshdImage = fmt.Sprintf(
49
        "tensorchord/envd-sshd-from-scratch:%s",
50
        version.GetVersionForImageTag())
51

52
var BaseEnvironment = []struct {
53
        Name  string
54
        Value string
55
}{
56
        {"DEBIAN_FRONTEND", "noninteractive"},
57
        {"PATH", DefaultSystemPath},
58
        {"LANG", "C.UTF-8"},
59
        {"LC_ALL", "C.UTF-8"},
60
}
61
var BaseAptPackage = []string{
62
        "bash-static",
63
        "libtinfo5",
64
        "libncursesw5",
65
        // conda dependencies
66
        "bzip2",
67
        "ca-certificates",
68
        "libglib2.0-0",
69
        "libsm6",
70
        "libxext6",
71
        "libxrender1",
72
        "mercurial",
73
        "procps",
74
        "subversion",
75
        "wget",
76
        // envd dependencies
77
        "curl",
78
        "openssh-client",
79
        "git",
80
        "sudo",
81
        "vim",
82
        "make",
83
        "zsh",
84
        "locales",
85
        "gpg", // used by r-lang
86
}
87

88
type EnvdImage struct {
89
        servertypes.ImageMeta `json:",inline,omitempty"`
90

91
        EnvdManifest `json:",inline,omitempty"`
92
}
93

94
type EnvdEnvironment struct {
95
        servertypes.Environment `json:",inline,omitempty"`
96

97
        EnvdManifest `json:",inline,omitempty"`
98
}
99

100
type EnvdManifest struct {
101
        GPU          bool   `json:"gpu,omitempty"`
102
        CUDA         string `json:"cuda,omitempty"`
103
        CUDNN        string `json:"cudnn,omitempty"`
104
        BuildContext string `json:"build_context,omitempty"`
105
        Dependency   `json:",inline,omitempty"`
106
}
107

108
type EnvdInfo struct {
109
        dockersystem.Info
110
}
111

112
type EnvdContext struct {
113
        Current  string    `json:"current,omitempty"`
114
        Contexts []Context `json:"contexts,omitempty"`
115
}
116

117
type Context struct {
118
        Name           string      `json:"name,omitempty"`
119
        Builder        BuilderType `json:"builder,omitempty"`
120
        BuilderAddress string      `json:"builder_address,omitempty"`
121
        Runner         RunnerType  `json:"runner,omitempty"`
122
        RunnerAddress  *string     `json:"runner_address,omitempty"`
123
}
124

125
type BuilderType string
126

127
const (
128
        BuilderTypeMoby             BuilderType = "moby-worker"
129
        BuilderTypeDocker           BuilderType = "docker-container"
130
        BuilderTypeNerdctl          BuilderType = "nerdctl-container"
131
        BuilderTypeKubernetes       BuilderType = "kube-pod"
132
        BuilderTypeTCP              BuilderType = "tcp"
133
        BuilderTypeUNIXDomainSocket BuilderType = "unix"
134
)
135

136
type RunnerType string
137

138
const (
139
        RunnerTypeDocker     RunnerType = "docker"
140
        RunnerTypeEnvdServer RunnerType = "envd-server"
141
)
142

143
type Dependency struct {
144
        APTPackages  []string `json:"apt_packages,omitempty"`
145
        PyPIPackages []string `json:"pypi_packages,omitempty"`
146
}
147

148
type RepoInfo struct {
149
        URL         string `json:"url,omitempty"`
150
        Description string `json:"description,omitempty"`
151
}
152

153
type OwnerInfo struct {
154
        Uid int64 `json:"uid,omitempty"`
155
        Gid int64 `json:"gid,omitempty"`
156
}
157

158
type PortBinding struct {
159
        Name     string
160
        Port     string
161
        Protocol string
162
        HostIP   string
163
        HostPort string
164
}
165

166
type EnvdAuth struct {
167
        Current string       `json:"current,omitempty"`
168
        Auth    []AuthConfig `json:"auth,omitempty"`
169
}
170

171
type AuthConfig struct {
172
        Name     string `json:"name,omitempty"`
173
        JWTToken string `json:"jwt_token,omitempty"`
174
}
175

176
func NewImageFromSummary(image image.Summary) (*EnvdImage, error) {
26✔
177
        img := EnvdImage{
26✔
178
                ImageMeta: servertypes.ImageMeta{
26✔
179
                        Digest:  image.ID,
26✔
180
                        Created: image.Created,
26✔
181
                        Size:    image.Size,
26✔
182
                        Labels:  image.Labels,
26✔
183
                },
26✔
184
        }
26✔
185
        if len(image.RepoTags) > 0 {
52✔
186
                img.Name = image.RepoTags[0]
26✔
187
        }
26✔
188
        m, err := newManifest(image.Labels)
26✔
189
        if err != nil {
26✔
190
                return nil, errors.Wrap(err, "failed to parse manifest")
×
191
        }
×
192
        img.EnvdManifest = m
26✔
193
        return &img, nil
26✔
194
}
195

196
func NewImageFromMeta(meta servertypes.ImageMeta) (*EnvdImage, error) {
×
197
        img := EnvdImage{
×
198
                ImageMeta: meta,
×
199
        }
×
200
        manifest, err := newManifest(img.Labels)
×
201
        if err != nil {
×
202
                return nil, err
×
203
        }
×
204
        img.EnvdManifest = manifest
×
205
        return &img, nil
×
206
}
207

208
func NewEnvironmentFromContainer(ctr container.Summary) (*EnvdEnvironment, error) {
×
209
        env := EnvdEnvironment{
×
210
                Environment: servertypes.Environment{
×
211
                        Spec:   servertypes.EnvironmentSpec{Image: ctr.Image},
×
212
                        Status: servertypes.EnvironmentStatus{Phase: ctr.Status},
×
213
                },
×
214
        }
×
215
        if name, ok := ctr.Labels[ContainerLabelName]; ok {
×
216
                env.Name = name
×
217
        }
×
218
        if jupyterAddr, ok := ctr.Labels[ContainerLabelJupyterAddr]; ok {
×
219
                env.Status.JupyterAddr = &jupyterAddr
×
220
        }
×
221
        if rstudioServerAddr, ok := ctr.Labels[ContainerLabelRStudioServerAddr]; ok {
×
222
                env.Status.RStudioServerAddr = &rstudioServerAddr
×
223
        }
×
224

225
        m, err := newManifest(ctr.Labels)
×
226
        if err != nil {
×
227
                return nil, err
×
228
        }
×
229
        env.EnvdManifest = m
×
230
        return &env, nil
×
231
}
232

233
func NewEnvironmentFromServer(ctr servertypes.Environment) (*EnvdEnvironment, error) {
×
234
        env := EnvdEnvironment{
×
235
                Environment: ctr,
×
236
        }
×
237

×
238
        m, err := newManifest(ctr.Labels)
×
239
        if err != nil {
×
240
                return nil, err
×
241
        }
×
242
        env.EnvdManifest = m
×
243
        return &env, nil
×
244
}
245

246
func newManifest(labels map[string]string) (EnvdManifest, error) {
26✔
247
        manifest := EnvdManifest{}
26✔
248
        if gpuEnabled, ok := labels[ImageLabelGPU]; ok {
26✔
249
                manifest.GPU = gpuEnabled == "true"
×
250
        }
×
251
        if cuda, ok := labels[ImageLabelCUDA]; ok {
26✔
252
                manifest.CUDA = cuda
×
253
        }
×
254
        if cudnn, ok := labels[ImageLabelCUDNN]; ok {
26✔
255
                manifest.CUDNN = cudnn
×
256
        }
×
257
        if context, ok := labels[ImageLabelContext]; ok {
52✔
258
                manifest.BuildContext = context
26✔
259
        }
26✔
260
        dep, err := NewDependencyFromLabels(labels)
26✔
261
        if err != nil {
26✔
262
                return manifest, err
×
263
        }
×
264
        manifest.Dependency = *dep
26✔
265
        return manifest, nil
26✔
266
}
267

268
func NewDependencyFromContainerJSON(ctr container.InspectResponse) (*Dependency, error) {
1✔
269
        return NewDependencyFromLabels(ctr.Config.Labels)
1✔
270
}
1✔
271

272
func NewDependencyFromImageSummary(img image.Summary) (*Dependency, error) {
×
273
        return NewDependencyFromLabels(img.Labels)
×
274
}
×
275

276
func NewPortBindingFromContainerJSON(ctr container.InspectResponse) ([]PortBinding, error) {
1✔
277
        var labels []servertypes.EnvironmentPort
1✔
278
        err := json.Unmarshal([]byte(ctr.Config.Labels[ImageLabelPorts]), &labels)
1✔
279
        if err != nil {
1✔
280
                return nil, err
×
281
        }
×
282

283
        var portMap = make(map[string]string)
1✔
284
        for _, label := range labels {
2✔
285
                portMap[fmt.Sprint(label.Port)] = label.Name
1✔
286
        }
1✔
287

288
        config := ctr.HostConfig.PortBindings
1✔
289
        var ports []PortBinding
1✔
290
        for port, bindings := range config {
2✔
291
                if len(bindings) <= 0 {
1✔
292
                        continue
×
293
                }
294
                binding := bindings[len(bindings)-1]
1✔
295
                ports = append(ports, PortBinding{
1✔
296
                        Name:     portMap[port.Port()],
1✔
297
                        Port:     port.Port(),
1✔
298
                        Protocol: port.Proto(),
1✔
299
                        HostIP:   binding.HostIP,
1✔
300
                        HostPort: binding.HostPort,
1✔
301
                })
1✔
302
        }
303

304
        return ports, nil
1✔
305
}
306

307
func NewDependencyFromLabels(label map[string]string) (*Dependency, error) {
27✔
308
        dep := Dependency{}
27✔
309
        if pkgs, ok := label[ImageLabelAPT]; ok {
54✔
310
                lst, err := parseAPTPackages(pkgs)
27✔
311
                if err != nil {
27✔
312
                        return nil, errors.Wrap(err, "failed to parse apt packages")
×
313
                }
×
314
                dep.APTPackages = lst
27✔
315
        }
316
        if pypiCommands, ok := label[ImageLabelPyPI]; ok {
54✔
317
                pkgs, err := parsePyPICommands(pypiCommands)
27✔
318
                if err != nil {
27✔
319
                        return nil, errors.Wrap(err, "failed to parse pypi commands")
×
320
                }
×
321
                dep.PyPIPackages = pkgs
27✔
322
        }
323
        return &dep, nil
27✔
324
}
325

326
func parseAPTPackages(lst string) ([]string, error) {
27✔
327
        var pkgs []string
27✔
328
        err := json.Unmarshal([]byte(lst), &pkgs)
27✔
329
        return pkgs, err
27✔
330
}
27✔
331

332
func parsePyPICommands(lst string) ([]string, error) {
27✔
333
        var pkgs []string
27✔
334
        err := json.Unmarshal([]byte(lst), &pkgs)
27✔
335
        return pkgs, err
27✔
336
}
27✔
337

338
func (c Context) GetSSHHostname(sshdHost string) (string, error) {
12✔
339
        if c.RunnerAddress == nil {
24✔
340
                return sshdHost, nil
12✔
341
        }
12✔
342

343
        // TODO(gaocegege): Check ENVD_SERVER_HOST.
344
        hostname, err := netutil.GetHost(*c.RunnerAddress)
×
345
        if err != nil {
×
346
                return "", err
×
347
        }
×
348
        return hostname, nil
×
349
}
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