Skip to content

Commit

Permalink
Update build tags, lint entire repo for Linux
Browse files Browse the repository at this point in the history
Add (Windows) build tags to necessary files, and add
`internal\vhdx\doc.go` so that go language server does not complain that
package is missing on Linux.

Not all updated files are Windows specific. Some (eg,
`internal\gcs\iochannel.go`) are only used by Windows code, so the go
build tag prevents `unused` lint errors when `GOOS=linux`.

Export the `parseAnnotations(Uint32|Uint64|String)` functions in
`internal\oci\annotations.go` since other functions in the
file are used in Linux files and that was the only way to avoid `unused`
lint errors.

Finally updated lint (in `.github\workflows\ci.yml`) and codeql
(in `.github\workflows\codeql.yml`) jobs to run on entire repo for
Linux, rather then specific directories.

Signed-off-by: Hamza El-Saawy <hamzaelsaawy@microsoft.com>
  • Loading branch information
helsaawy committed Nov 13, 2023
1 parent 79ab3ee commit b80bd98
Show file tree
Hide file tree
Showing 33 changed files with 89 additions and 61 deletions.
16 changes: 3 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,6 @@ jobs:
matrix:
goos: [windows, linux]
root: ["", test] # cannot specify "./... ./test/..." unless in go workspace
include:
- goos: linux
root: ""
dirs: >-
./cmd/gcs/...
./cmd/gcstools/...
./internal/guest...
./internal/tools/...
./pkg/...
./ext4/...

steps:
- name: Checkout
Expand All @@ -43,15 +33,15 @@ jobs:
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.52
version: v1.54
args: >-
--verbose
--max-issues-per-linter=0
--max-same-issues=0
--modules-download-mode=readonly
--timeout=10m
${{ matrix.dirs }}
working-directory: ${{ matrix.root }}
--config=${{ github.workspace }}/.golangci.yml
working-directory: ${{ github.workspace }}/${{ matrix.root }}
env:
GOOS: ${{ matrix.goos }}

Expand Down
10 changes: 0 additions & 10 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,6 @@ jobs:
fail-fast: false
matrix:
goos: [windows, linux]
include:
- goos: linux
root: ""
dirs: >-
./cmd/gcs/...
./cmd/gcstools/...
./cmd/dmverity-vhd/...
./cmd/hooks/...
./internal/guest...
./internal/tools/...

steps:
- name: Checkout
Expand Down
2 changes: 2 additions & 0 deletions cmd/containerd-shim-runhcs-v1/rootfs.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package main

import (
Expand Down
2 changes: 2 additions & 0 deletions cmd/ncproxy/ncproxy_v0_service.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package main

import (
Expand Down
2 changes: 2 additions & 0 deletions cmd/ncproxy/ncproxy_v0_service_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package main

import (
Expand Down
2 changes: 2 additions & 0 deletions cmd/ncproxy/utilities_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package main

import (
Expand Down
2 changes: 2 additions & 0 deletions internal/gcs/iochannel.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package gcs

import (
Expand Down
12 changes: 6 additions & 6 deletions internal/oci/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,9 @@ func ParseAnnotationsNullableBool(ctx context.Context, a map[string]string, key
return nil
}

// parseAnnotationsUint32 searches `a` for `key` and if found verifies that the
// ParseAnnotationsUint32 searches `a` for `key` and if found verifies that the
// value is a 32 bit unsigned integer. If `key` is not found returns `def`.
func parseAnnotationsUint32(ctx context.Context, a map[string]string, key string, def uint32) uint32 {
func ParseAnnotationsUint32(ctx context.Context, a map[string]string, key string, def uint32) uint32 {
if v, ok := a[key]; ok {
countu, err := strconv.ParseUint(v, 10, 32)
if err == nil {
Expand All @@ -235,9 +235,9 @@ func parseAnnotationsUint32(ctx context.Context, a map[string]string, key string
return def
}

// parseAnnotationsUint64 searches `a` for `key` and if found verifies that the
// ParseAnnotationsUint64 searches `a` for `key` and if found verifies that the
// value is a 64 bit unsigned integer. If `key` is not found returns `def`.
func parseAnnotationsUint64(ctx context.Context, a map[string]string, key string, def uint64) uint64 {
func ParseAnnotationsUint64(ctx context.Context, a map[string]string, key string, def uint64) uint64 {
if v, ok := a[key]; ok {
countu, err := strconv.ParseUint(v, 10, 64)
if err == nil {
Expand All @@ -248,8 +248,8 @@ func parseAnnotationsUint64(ctx context.Context, a map[string]string, key string
return def
}

// parseAnnotationsString searches `a` for `key`. If `key` is not found returns `def`.
func parseAnnotationsString(a map[string]string, key string, def string) string {
// ParseAnnotationsString searches `a` for `key`. If `key` is not found returns `def`.
func ParseAnnotationsString(a map[string]string, key string, def string) string {
if v, ok := a[key]; ok {
return v
}
Expand Down
44 changes: 22 additions & 22 deletions internal/oci/uvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
// not found searches `s` for the Windows CPU section. If neither are found
// returns `def`.
func ParseAnnotationsCPUCount(ctx context.Context, s *specs.Spec, annotation string, def int32) int32 {
if m := parseAnnotationsUint64(ctx, s.Annotations, annotation, 0); m != 0 {
if m := ParseAnnotationsUint64(ctx, s.Annotations, annotation, 0); m != 0 {
return int32(m)
}
if s.Windows != nil &&
Expand All @@ -38,7 +38,7 @@ func ParseAnnotationsCPUCount(ctx context.Context, s *specs.Spec, annotation str
// not found searches `s` for the Windows CPU section. If neither are found
// returns `def`.
func ParseAnnotationsCPULimit(ctx context.Context, s *specs.Spec, annotation string, def int32) int32 {
if m := parseAnnotationsUint64(ctx, s.Annotations, annotation, 0); m != 0 {
if m := ParseAnnotationsUint64(ctx, s.Annotations, annotation, 0); m != 0 {
return int32(m)
}
if s.Windows != nil &&
Expand All @@ -55,7 +55,7 @@ func ParseAnnotationsCPULimit(ctx context.Context, s *specs.Spec, annotation str
// not found searches `s` for the Windows CPU section. If neither are found
// returns `def`.
func ParseAnnotationsCPUWeight(ctx context.Context, s *specs.Spec, annotation string, def int32) int32 {
if m := parseAnnotationsUint64(ctx, s.Annotations, annotation, 0); m != 0 {
if m := ParseAnnotationsUint64(ctx, s.Annotations, annotation, 0); m != 0 {
return int32(m)
}
if s.Windows != nil &&
Expand All @@ -72,7 +72,7 @@ func ParseAnnotationsCPUWeight(ctx context.Context, s *specs.Spec, annotation st
// annotation. If not found searches `s` for the Windows Storage section. If
// neither are found returns `def`.
func ParseAnnotationsStorageIops(ctx context.Context, s *specs.Spec, annotation string, def int32) int32 {
if m := parseAnnotationsUint64(ctx, s.Annotations, annotation, 0); m != 0 {
if m := ParseAnnotationsUint64(ctx, s.Annotations, annotation, 0); m != 0 {
return int32(m)
}
if s.Windows != nil &&
Expand All @@ -89,7 +89,7 @@ func ParseAnnotationsStorageIops(ctx context.Context, s *specs.Spec, annotation
// If not found searches `s` for the Windows Storage section. If neither are
// found returns `def`.
func ParseAnnotationsStorageBps(ctx context.Context, s *specs.Spec, annotation string, def int32) int32 {
if m := parseAnnotationsUint64(ctx, s.Annotations, annotation, 0); m != 0 {
if m := ParseAnnotationsUint64(ctx, s.Annotations, annotation, 0); m != 0 {
return int32(m)
}
if s.Windows != nil &&
Expand All @@ -108,7 +108,7 @@ func ParseAnnotationsStorageBps(ctx context.Context, s *specs.Spec, annotation s
//
// Note: The returned value is in `MB`.
func ParseAnnotationsMemory(ctx context.Context, s *specs.Spec, annotation string, def uint64) uint64 {
if m := parseAnnotationsUint64(ctx, s.Annotations, annotation, 0); m != 0 {
if m := ParseAnnotationsUint64(ctx, s.Annotations, annotation, 0); m != 0 {
return m
}
if s.Windows != nil &&
Expand Down Expand Up @@ -143,7 +143,7 @@ func parseAnnotationsPreferredRootFSType(ctx context.Context, a map[string]strin
// handleAnnotationBootFilesPath handles parsing annotations.BootFilesRootPath and setting
// implied options from the result.
func handleAnnotationBootFilesPath(ctx context.Context, a map[string]string, lopts *uvm.OptionsLCOW) {
lopts.UpdateBootFilesPath(ctx, parseAnnotationsString(a, annotations.BootFilesRootPath, lopts.BootFilesPath))
lopts.UpdateBootFilesPath(ctx, ParseAnnotationsString(a, annotations.BootFilesRootPath, lopts.BootFilesPath))
}

// handleAnnotationKernelDirectBoot handles parsing annotations.KernelDirectBoot and setting
Expand Down Expand Up @@ -190,7 +190,7 @@ func handleAnnotationFullyPhysicallyBacked(ctx context.Context, a map[string]str
// handleSecurityPolicy handles parsing SecurityPolicy and NoSecurityHardware and setting
// implied options from the results. Both LCOW only, not WCOW
func handleSecurityPolicy(ctx context.Context, a map[string]string, lopts *uvm.OptionsLCOW) {
lopts.SecurityPolicy = parseAnnotationsString(a, annotations.SecurityPolicy, lopts.SecurityPolicy)
lopts.SecurityPolicy = ParseAnnotationsString(a, annotations.SecurityPolicy, lopts.SecurityPolicy)
// allow actual isolated boot etc to be ignored if we have no hardware. Required for dev
// this is not a security issue as the attestation will fail without a genuine report
noSecurityHardware := ParseAnnotationsBool(ctx, a, annotations.NoSecurityHardware, false)
Expand Down Expand Up @@ -219,21 +219,21 @@ func handleSecurityPolicy(ctx context.Context, a map[string]string, lopts *uvm.O
// sets options common to both WCOW and LCOW from annotations
func specToUVMCreateOptionsCommon(ctx context.Context, opts *uvm.Options, s *specs.Spec) {
opts.MemorySizeInMB = ParseAnnotationsMemory(ctx, s, annotations.MemorySizeInMB, opts.MemorySizeInMB)
opts.LowMMIOGapInMB = parseAnnotationsUint64(ctx, s.Annotations, annotations.MemoryLowMMIOGapInMB, opts.LowMMIOGapInMB)
opts.HighMMIOBaseInMB = parseAnnotationsUint64(ctx, s.Annotations, annotations.MemoryHighMMIOBaseInMB, opts.HighMMIOBaseInMB)
opts.HighMMIOGapInMB = parseAnnotationsUint64(ctx, s.Annotations, annotations.MemoryHighMMIOGapInMB, opts.HighMMIOGapInMB)
opts.LowMMIOGapInMB = ParseAnnotationsUint64(ctx, s.Annotations, annotations.MemoryLowMMIOGapInMB, opts.LowMMIOGapInMB)
opts.HighMMIOBaseInMB = ParseAnnotationsUint64(ctx, s.Annotations, annotations.MemoryHighMMIOBaseInMB, opts.HighMMIOBaseInMB)
opts.HighMMIOGapInMB = ParseAnnotationsUint64(ctx, s.Annotations, annotations.MemoryHighMMIOGapInMB, opts.HighMMIOGapInMB)
opts.AllowOvercommit = ParseAnnotationsBool(ctx, s.Annotations, annotations.AllowOvercommit, opts.AllowOvercommit)
opts.EnableDeferredCommit = ParseAnnotationsBool(ctx, s.Annotations, annotations.EnableDeferredCommit, opts.EnableDeferredCommit)
opts.ProcessorCount = ParseAnnotationsCPUCount(ctx, s, annotations.ProcessorCount, opts.ProcessorCount)
opts.ProcessorLimit = ParseAnnotationsCPULimit(ctx, s, annotations.ProcessorLimit, opts.ProcessorLimit)
opts.ProcessorWeight = ParseAnnotationsCPUWeight(ctx, s, annotations.ProcessorWeight, opts.ProcessorWeight)
opts.StorageQoSBandwidthMaximum = ParseAnnotationsStorageBps(ctx, s, annotations.StorageQoSBandwidthMaximum, opts.StorageQoSBandwidthMaximum)
opts.StorageQoSIopsMaximum = ParseAnnotationsStorageIops(ctx, s, annotations.StorageQoSIopsMaximum, opts.StorageQoSIopsMaximum)
opts.CPUGroupID = parseAnnotationsString(s.Annotations, annotations.CPUGroupID, opts.CPUGroupID)
opts.NetworkConfigProxy = parseAnnotationsString(s.Annotations, annotations.NetworkConfigProxy, opts.NetworkConfigProxy)
opts.ProcessDumpLocation = parseAnnotationsString(s.Annotations, annotations.ContainerProcessDumpLocation, opts.ProcessDumpLocation)
opts.CPUGroupID = ParseAnnotationsString(s.Annotations, annotations.CPUGroupID, opts.CPUGroupID)
opts.NetworkConfigProxy = ParseAnnotationsString(s.Annotations, annotations.NetworkConfigProxy, opts.NetworkConfigProxy)
opts.ProcessDumpLocation = ParseAnnotationsString(s.Annotations, annotations.ContainerProcessDumpLocation, opts.ProcessDumpLocation)
opts.NoWritableFileShares = ParseAnnotationsBool(ctx, s.Annotations, annotations.DisableWritableFileShares, opts.NoWritableFileShares)
opts.DumpDirectoryPath = parseAnnotationsString(s.Annotations, annotations.DumpDirectoryPath, opts.DumpDirectoryPath)
opts.DumpDirectoryPath = ParseAnnotationsString(s.Annotations, annotations.DumpDirectoryPath, opts.DumpDirectoryPath)
}

// SpecToUVMCreateOpts parses `s` and returns either `*uvm.OptionsLCOW` or
Expand All @@ -256,16 +256,16 @@ func SpecToUVMCreateOpts(ctx context.Context, s *specs.Spec, id, owner string) (
*/

lopts.EnableColdDiscardHint = ParseAnnotationsBool(ctx, s.Annotations, annotations.EnableColdDiscardHint, lopts.EnableColdDiscardHint)
lopts.VPMemDeviceCount = parseAnnotationsUint32(ctx, s.Annotations, annotations.VPMemCount, lopts.VPMemDeviceCount)
lopts.VPMemSizeBytes = parseAnnotationsUint64(ctx, s.Annotations, annotations.VPMemSize, lopts.VPMemSizeBytes)
lopts.VPMemDeviceCount = ParseAnnotationsUint32(ctx, s.Annotations, annotations.VPMemCount, lopts.VPMemDeviceCount)
lopts.VPMemSizeBytes = ParseAnnotationsUint64(ctx, s.Annotations, annotations.VPMemSize, lopts.VPMemSizeBytes)
lopts.VPMemNoMultiMapping = ParseAnnotationsBool(ctx, s.Annotations, annotations.VPMemNoMultiMapping, lopts.VPMemNoMultiMapping)
lopts.VPCIEnabled = ParseAnnotationsBool(ctx, s.Annotations, annotations.VPCIEnabled, lopts.VPCIEnabled)
handleAnnotationBootFilesPath(ctx, s.Annotations, lopts)
lopts.EnableScratchEncryption = ParseAnnotationsBool(ctx, s.Annotations, annotations.EncryptedScratchDisk, lopts.EnableScratchEncryption)
lopts.SecurityPolicy = parseAnnotationsString(s.Annotations, annotations.SecurityPolicy, lopts.SecurityPolicy)
lopts.SecurityPolicyEnforcer = parseAnnotationsString(s.Annotations, annotations.SecurityPolicyEnforcer, lopts.SecurityPolicyEnforcer)
lopts.UVMReferenceInfoFile = parseAnnotationsString(s.Annotations, annotations.UVMReferenceInfoFile, lopts.UVMReferenceInfoFile)
lopts.KernelBootOptions = parseAnnotationsString(s.Annotations, annotations.KernelBootOptions, lopts.KernelBootOptions)
lopts.SecurityPolicy = ParseAnnotationsString(s.Annotations, annotations.SecurityPolicy, lopts.SecurityPolicy)
lopts.SecurityPolicyEnforcer = ParseAnnotationsString(s.Annotations, annotations.SecurityPolicyEnforcer, lopts.SecurityPolicyEnforcer)
lopts.UVMReferenceInfoFile = ParseAnnotationsString(s.Annotations, annotations.UVMReferenceInfoFile, lopts.UVMReferenceInfoFile)
lopts.KernelBootOptions = ParseAnnotationsString(s.Annotations, annotations.KernelBootOptions, lopts.KernelBootOptions)
lopts.DisableTimeSyncService = ParseAnnotationsBool(ctx, s.Annotations, annotations.DisableLCOWTimeSyncService, lopts.DisableTimeSyncService)
handleAnnotationPreferredRootFSType(ctx, s.Annotations, lopts)
handleAnnotationKernelDirectBoot(ctx, s.Annotations, lopts)
Expand All @@ -279,7 +279,7 @@ func SpecToUVMCreateOpts(ctx context.Context, s *specs.Spec, id, owner string) (
handleSecurityPolicy(ctx, s.Annotations, lopts)

// override the default GuestState filename if specified
lopts.GuestStateFile = parseAnnotationsString(s.Annotations, annotations.GuestStateFile, lopts.GuestStateFile)
lopts.GuestStateFile = ParseAnnotationsString(s.Annotations, annotations.GuestStateFile, lopts.GuestStateFile)
// Set HclEnabled if specified. Else default to a null pointer, which is omitted from the resulting JSON.
lopts.HclEnabled = ParseAnnotationsNullableBool(ctx, s.Annotations, annotations.HclEnabled)
return lopts, nil
Expand Down
2 changes: 2 additions & 0 deletions internal/uvm/constants.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package uvm

import (
Expand Down
2 changes: 2 additions & 0 deletions internal/uvm/scsi/attach.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package scsi

import (
Expand Down
2 changes: 2 additions & 0 deletions internal/uvm/scsi/backend.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package scsi

import (
Expand Down
2 changes: 2 additions & 0 deletions internal/uvm/scsi/manager.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package scsi

import (
Expand Down
2 changes: 2 additions & 0 deletions internal/uvm/scsi/mount.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package scsi

import (
Expand Down
3 changes: 3 additions & 0 deletions internal/vhdx/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// vhdx package adds the utility methods necessary to deal with the vhdx that are used as the scratch
// space for the containers and the uvm.
package vhdx
4 changes: 2 additions & 2 deletions internal/vhdx/info.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// vhdx package adds the utility methods necessary to deal with the vhdx that are used as the scratch
// space for the containers and the uvm.
//go:build windows

package vhdx

import (
Expand Down
2 changes: 2 additions & 0 deletions internal/wclayer/baselayerreader.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package wclayer

import (
Expand Down
2 changes: 2 additions & 0 deletions internal/wclayer/cim/LayerWriter.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package cim

import (
Expand Down
2 changes: 2 additions & 0 deletions internal/wclayer/cim/bcd.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package cim

import (
Expand Down
2 changes: 2 additions & 0 deletions internal/wclayer/cim/common.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package cim

import (
Expand Down
3 changes: 3 additions & 0 deletions internal/wclayer/cim/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// This package provides utilities for working with container image layers in the cim format
// via the wclayer APIs.
package cim
2 changes: 2 additions & 0 deletions internal/wclayer/cim/file_writer.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package cim

import (
Expand Down
2 changes: 2 additions & 0 deletions internal/wclayer/cim/pending.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package cim

import (
Expand Down
2 changes: 2 additions & 0 deletions internal/wclayer/cim/process.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package cim

import (
Expand Down
2 changes: 2 additions & 0 deletions internal/wclayer/cim/registry.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package cim

import (
Expand Down
2 changes: 2 additions & 0 deletions internal/wclayer/converttobaselayer.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package wclayer

import (
Expand Down
2 changes: 2 additions & 0 deletions internal/winapi/cimfs.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build windows

package winapi

import (
Expand Down
3 changes: 3 additions & 0 deletions pkg/amdsevsnp/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Package amdsevsnp contains minimal functionality required to fetch
// attestation reports inside an enlightened guest.
package amdsevsnp
2 changes: 0 additions & 2 deletions pkg/amdsevsnp/report.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
//go:build linux
// +build linux

// Package amdsevsnp contains minimal functionality required to fetch
// attestation reports inside an enlightened guest.
package amdsevsnp

import (
Expand Down
3 changes: 3 additions & 0 deletions pkg/cimfs/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// This package provides simple go wrappers on top of the win32 CIMFS mount APIs.
// The mounting/unmount of cim layers is done by the cim mount functions the internal/wclayer/cim package.
package cimfs
4 changes: 4 additions & 0 deletions pkg/cimfs/format/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// format package maintains some basic structures to allows us to read header of a cim file. This is mostly
// required to understand the region & objectid files associated with a particular cim. Otherwise, we don't
// need to parse the cim format.
package format
3 changes: 0 additions & 3 deletions pkg/cimfs/format/format.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
//go:build windows
// +build windows

// format package maintains some basic structures to allows us to read header of a cim file. This is mostly
// required to understand the region & objectid files associated with a particular cim. Otherwise, we don't
// need to parse the cim format.
package format

import "github.com/Microsoft/go-winio/pkg/guid"
Expand Down
3 changes: 0 additions & 3 deletions pkg/cimfs/mount_cim.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ import (
"github.com/pkg/errors"
)

// This package provides simple go wrappers on top of the win32 CIMFS mount APIs. The mounting/unmount of cim
// layers is done by the cim mount functions in internal/wclayer/cim package.

type MountError struct {
Cim string
Op string
Expand Down

0 comments on commit b80bd98

Please sign in to comment.