mirror of
https://github.com/lxc/incus.git
synced 2026-02-05 09:46:19 +01:00
client: Make golangci-lint clean
Signed-off-by: Stéphane Graber <stgraber@stgraber.org>
This commit is contained in:
@@ -74,8 +74,8 @@ type ConnectionArgs struct {
|
||||
// If connecting to an Incus daemon running in PKI mode, the PKI CA (TLSCA) must also be provided.
|
||||
//
|
||||
// Unless the remote server is trusted by the system CA, the remote certificate must be provided (TLSServerCert).
|
||||
func ConnectIncus(url string, args *ConnectionArgs) (InstanceServer, error) {
|
||||
return ConnectIncusWithContext(context.Background(), url, args)
|
||||
func ConnectIncus(uri string, args *ConnectionArgs) (InstanceServer, error) {
|
||||
return ConnectIncusWithContext(context.Background(), uri, args)
|
||||
}
|
||||
|
||||
// ConnectIncusWithContext lets you connect to a remote Incus daemon over HTTPs with context.Context.
|
||||
@@ -85,13 +85,13 @@ func ConnectIncus(url string, args *ConnectionArgs) (InstanceServer, error) {
|
||||
// If connecting to an Incus daemon running in PKI mode, the PKI CA (TLSCA) must also be provided.
|
||||
//
|
||||
// Unless the remote server is trusted by the system CA, the remote certificate must be provided (TLSServerCert).
|
||||
func ConnectIncusWithContext(ctx context.Context, url string, args *ConnectionArgs) (InstanceServer, error) {
|
||||
func ConnectIncusWithContext(ctx context.Context, uri string, args *ConnectionArgs) (InstanceServer, error) {
|
||||
// Cleanup URL
|
||||
url = strings.TrimSuffix(url, "/")
|
||||
uri = strings.TrimSuffix(uri, "/")
|
||||
|
||||
logger.Debug("Connecting to a remote Incus over HTTPS", logger.Ctx{"url": url})
|
||||
logger.Debug("Connecting to a remote Incus over HTTPS", logger.Ctx{"url": uri})
|
||||
|
||||
return httpsIncus(ctx, url, args)
|
||||
return httpsIncus(ctx, uri, args)
|
||||
}
|
||||
|
||||
// ConnectIncusHTTP lets you connect to a VM agent over a VM socket.
|
||||
@@ -240,30 +240,30 @@ func ConnectIncusUnixWithContext(ctx context.Context, path string, args *Connect
|
||||
// ConnectPublicIncus lets you connect to a remote public Incus daemon over HTTPs.
|
||||
//
|
||||
// Unless the remote server is trusted by the system CA, the remote certificate must be provided (TLSServerCert).
|
||||
func ConnectPublicIncus(url string, args *ConnectionArgs) (ImageServer, error) {
|
||||
return ConnectPublicIncusWithContext(context.Background(), url, args)
|
||||
func ConnectPublicIncus(uri string, args *ConnectionArgs) (ImageServer, error) {
|
||||
return ConnectPublicIncusWithContext(context.Background(), uri, args)
|
||||
}
|
||||
|
||||
// ConnectPublicIncusWithContext lets you connect to a remote public Incus daemon over HTTPs with context.Context.
|
||||
//
|
||||
// Unless the remote server is trusted by the system CA, the remote certificate must be provided (TLSServerCert).
|
||||
func ConnectPublicIncusWithContext(ctx context.Context, url string, args *ConnectionArgs) (ImageServer, error) {
|
||||
func ConnectPublicIncusWithContext(ctx context.Context, uri string, args *ConnectionArgs) (ImageServer, error) {
|
||||
logger.Debug("Connecting to a remote public Incus over HTTPS")
|
||||
|
||||
// Cleanup URL
|
||||
url = strings.TrimSuffix(url, "/")
|
||||
uri = strings.TrimSuffix(uri, "/")
|
||||
|
||||
return httpsIncus(ctx, url, args)
|
||||
return httpsIncus(ctx, uri, args)
|
||||
}
|
||||
|
||||
// ConnectSimpleStreams lets you connect to a remote SimpleStreams image server over HTTPs.
|
||||
//
|
||||
// Unless the remote server is trusted by the system CA, the remote certificate must be provided (TLSServerCert).
|
||||
func ConnectSimpleStreams(url string, args *ConnectionArgs) (ImageServer, error) {
|
||||
logger.Debug("Connecting to a remote simplestreams server", logger.Ctx{"URL": url})
|
||||
func ConnectSimpleStreams(uri string, args *ConnectionArgs) (ImageServer, error) {
|
||||
logger.Debug("Connecting to a remote simplestreams server", logger.Ctx{"URL": uri})
|
||||
|
||||
// Cleanup URL
|
||||
url = strings.TrimSuffix(url, "/")
|
||||
uri = strings.TrimSuffix(uri, "/")
|
||||
|
||||
// Use empty args if not specified
|
||||
if args == nil {
|
||||
@@ -272,7 +272,7 @@ func ConnectSimpleStreams(url string, args *ConnectionArgs) (ImageServer, error)
|
||||
|
||||
// Initialize the client struct
|
||||
server := ProtocolSimpleStreams{
|
||||
httpHost: url,
|
||||
httpHost: uri,
|
||||
httpUserAgent: args.UserAgent,
|
||||
httpCertificate: args.TLSServerCert,
|
||||
}
|
||||
@@ -286,7 +286,7 @@ func ConnectSimpleStreams(url string, args *ConnectionArgs) (ImageServer, error)
|
||||
server.http = httpClient
|
||||
|
||||
// Get simplestreams client
|
||||
ssClient := simplestreams.NewClient(url, *httpClient, args.UserAgent)
|
||||
ssClient := simplestreams.NewClient(uri, *httpClient, args.UserAgent)
|
||||
server.ssClient = ssClient
|
||||
|
||||
// Setup the cache
|
||||
@@ -295,7 +295,7 @@ func ConnectSimpleStreams(url string, args *ConnectionArgs) (ImageServer, error)
|
||||
return nil, fmt.Errorf("Cache directory %q doesn't exist", args.CachePath)
|
||||
}
|
||||
|
||||
hashedURL := fmt.Sprintf("%x", sha256.Sum256([]byte(url)))
|
||||
hashedURL := fmt.Sprintf("%x", sha256.Sum256([]byte(uri)))
|
||||
|
||||
cachePath := filepath.Join(args.CachePath, hashedURL)
|
||||
cacheExpiry := args.CacheExpiry
|
||||
|
||||
@@ -2,6 +2,7 @@ package incus
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime"
|
||||
@@ -129,7 +130,12 @@ func (r *ProtocolIncus) GetImageSecret(fingerprint string) (string, error) {
|
||||
|
||||
opAPI := op.Get()
|
||||
|
||||
return opAPI.Metadata["secret"].(string), nil
|
||||
secret, ok := opAPI.Metadata["secret"].(string)
|
||||
if !ok {
|
||||
return "", errors.New("Bad secret type")
|
||||
}
|
||||
|
||||
return secret, nil
|
||||
}
|
||||
|
||||
// GetPrivateImage is similar to GetImage but allows passing a secret download token.
|
||||
@@ -273,7 +279,7 @@ func incusDownloadImage(fingerprint string, uri string, userAgent string, do fun
|
||||
}
|
||||
|
||||
// Hashing
|
||||
sha256 := sha256.New()
|
||||
hashSHA256 := sha256.New()
|
||||
|
||||
// Deal with split images
|
||||
if ctype == "multipart/form-data" {
|
||||
@@ -294,7 +300,7 @@ func incusDownloadImage(fingerprint string, uri string, userAgent string, do fun
|
||||
return nil, fmt.Errorf("Invalid multipart image")
|
||||
}
|
||||
|
||||
size, err := io.Copy(io.MultiWriter(req.MetaFile, sha256), part)
|
||||
size, err := io.Copy(io.MultiWriter(req.MetaFile, hashSHA256), part)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -312,7 +318,7 @@ func incusDownloadImage(fingerprint string, uri string, userAgent string, do fun
|
||||
return nil, fmt.Errorf("Invalid multipart image")
|
||||
}
|
||||
|
||||
size, err = io.Copy(io.MultiWriter(req.RootfsFile, sha256), part)
|
||||
size, err = io.Copy(io.MultiWriter(req.RootfsFile, hashSHA256), part)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -321,7 +327,7 @@ func incusDownloadImage(fingerprint string, uri string, userAgent string, do fun
|
||||
resp.RootfsName = part.FileName()
|
||||
|
||||
// Check the hash
|
||||
hash := fmt.Sprintf("%x", sha256.Sum(nil))
|
||||
hash := fmt.Sprintf("%x", hashSHA256.Sum(nil))
|
||||
if imageType != "oci" && !strings.HasPrefix(hash, fingerprint) {
|
||||
return nil, fmt.Errorf("Image fingerprint doesn't match. Got %s expected %s", hash, fingerprint)
|
||||
}
|
||||
@@ -340,7 +346,7 @@ func incusDownloadImage(fingerprint string, uri string, userAgent string, do fun
|
||||
return nil, fmt.Errorf("No filename in Content-Disposition header")
|
||||
}
|
||||
|
||||
size, err := io.Copy(io.MultiWriter(req.MetaFile, sha256), body)
|
||||
size, err := io.Copy(io.MultiWriter(req.MetaFile, hashSHA256), body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -349,7 +355,7 @@ func incusDownloadImage(fingerprint string, uri string, userAgent string, do fun
|
||||
resp.MetaName = filename
|
||||
|
||||
// Check the hash
|
||||
hash := fmt.Sprintf("%x", sha256.Sum(nil))
|
||||
hash := fmt.Sprintf("%x", hashSHA256.Sum(nil))
|
||||
if imageType != "oci" && !strings.HasPrefix(hash, fingerprint) {
|
||||
return nil, fmt.Errorf("Image fingerprint doesn't match. Got %s expected %s", hash, fingerprint)
|
||||
}
|
||||
@@ -653,18 +659,23 @@ func (r *ProtocolIncus) tryCopyImage(req api.ImagesPost, urls []string) (RemoteO
|
||||
return
|
||||
}
|
||||
|
||||
var errors []remoteOperationResult
|
||||
var errs []remoteOperationResult
|
||||
|
||||
// Get the operation data
|
||||
op, err := rop.GetTarget()
|
||||
if err != nil {
|
||||
errors = append(errors, remoteOperationResult{Error: err})
|
||||
rop.err = remoteOperationError("Failed to get operation data", errors)
|
||||
errs = append(errs, remoteOperationResult{Error: err})
|
||||
rop.err = remoteOperationError("Failed to get operation data", errs)
|
||||
return
|
||||
}
|
||||
|
||||
// Extract the fingerprint
|
||||
fingerprint := op.Metadata["fingerprint"].(string)
|
||||
fingerprint, ok := op.Metadata["fingerprint"].(string)
|
||||
if !ok {
|
||||
errs = append(errs, remoteOperationResult{Error: errors.New("Bad fingerprint")})
|
||||
rop.err = remoteOperationError("Failed to get operation data", errs)
|
||||
return
|
||||
}
|
||||
|
||||
// Add the aliases
|
||||
for _, entry := range req.Aliases {
|
||||
@@ -674,8 +685,8 @@ func (r *ProtocolIncus) tryCopyImage(req api.ImagesPost, urls []string) (RemoteO
|
||||
|
||||
err := r.CreateImageAlias(alias)
|
||||
if err != nil {
|
||||
errors = append(errors, remoteOperationResult{Error: err})
|
||||
rop.err = remoteOperationError("Failed to create image alias", errors)
|
||||
errs = append(errs, remoteOperationResult{Error: err})
|
||||
rop.err = remoteOperationError("Failed to create image alias", errs)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -685,13 +696,13 @@ func (r *ProtocolIncus) tryCopyImage(req api.ImagesPost, urls []string) (RemoteO
|
||||
// Forward targetOp to remote op
|
||||
go func() {
|
||||
success := false
|
||||
var errors []remoteOperationResult
|
||||
var errs []remoteOperationResult
|
||||
for _, serverURL := range urls {
|
||||
req.Source.Server = serverURL
|
||||
|
||||
op, err := r.CreateImage(req, nil)
|
||||
if err != nil {
|
||||
errors = append(errors, remoteOperationResult{URL: serverURL, Error: err})
|
||||
errs = append(errs, remoteOperationResult{URL: serverURL, Error: err})
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -705,7 +716,7 @@ func (r *ProtocolIncus) tryCopyImage(req api.ImagesPost, urls []string) (RemoteO
|
||||
|
||||
err = rop.targetOp.Wait()
|
||||
if err != nil {
|
||||
errors = append(errors, remoteOperationResult{URL: serverURL, Error: err})
|
||||
errs = append(errs, remoteOperationResult{URL: serverURL, Error: err})
|
||||
|
||||
if localtls.IsConnectionError(err) {
|
||||
continue
|
||||
@@ -719,7 +730,7 @@ func (r *ProtocolIncus) tryCopyImage(req api.ImagesPost, urls []string) (RemoteO
|
||||
}
|
||||
|
||||
if !success {
|
||||
rop.err = remoteOperationError("Failed remote image download", errors)
|
||||
rop.err = remoteOperationError("Failed remote image download", errs)
|
||||
}
|
||||
|
||||
close(rop.chDone)
|
||||
|
||||
@@ -884,7 +884,10 @@ func (r *ProtocolIncus) CopyInstance(source InstanceServer, instance api.Instanc
|
||||
|
||||
targetSecrets := map[string]string{}
|
||||
for k, v := range opAPI.Metadata {
|
||||
targetSecrets[k] = v.(string)
|
||||
val, ok := v.(string)
|
||||
if ok {
|
||||
targetSecrets[k] = val
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the source request
|
||||
@@ -912,7 +915,10 @@ func (r *ProtocolIncus) CopyInstance(source InstanceServer, instance api.Instanc
|
||||
|
||||
sourceSecrets := map[string]string{}
|
||||
for k, v := range opAPI.Metadata {
|
||||
sourceSecrets[k] = v.(string)
|
||||
val, ok := v.(string)
|
||||
if ok {
|
||||
sourceSecrets[k] = val
|
||||
}
|
||||
}
|
||||
|
||||
// Relay mode migration
|
||||
@@ -932,7 +938,10 @@ func (r *ProtocolIncus) CopyInstance(source InstanceServer, instance api.Instanc
|
||||
// Extract the websockets
|
||||
targetSecrets := map[string]string{}
|
||||
for k, v := range targetOpAPI.Metadata {
|
||||
targetSecrets[k] = v.(string)
|
||||
val, ok := v.(string)
|
||||
if ok {
|
||||
targetSecrets[k] = val
|
||||
}
|
||||
}
|
||||
|
||||
// Launch the relay
|
||||
@@ -1190,9 +1199,14 @@ func (r *ProtocolIncus) ExecInstance(instanceName string, exec api.InstanceExecP
|
||||
|
||||
value, ok := opAPI.Metadata["fds"]
|
||||
if ok {
|
||||
values := value.(map[string]any)
|
||||
for k, v := range values {
|
||||
fds[k] = v.(string)
|
||||
values, ok := value.(map[string]any)
|
||||
if ok {
|
||||
for k, v := range values {
|
||||
val, ok := v.(string)
|
||||
if ok {
|
||||
fds[k] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1207,7 +1221,10 @@ func (r *ProtocolIncus) ExecInstance(instanceName string, exec api.InstanceExecP
|
||||
outputs, ok := opAPI.Metadata["output"].(map[string]any)
|
||||
if ok {
|
||||
for k, v := range outputs {
|
||||
outputFiles[k] = v.(string)
|
||||
val, ok := v.(string)
|
||||
if ok {
|
||||
outputFiles[k] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1811,7 +1828,7 @@ func (r *ProtocolIncus) CopyInstanceSnapshot(source InstanceServer, instanceName
|
||||
return nil, fmt.Errorf("The server is missing the required \"container_snapshot_stateful_migration\" API extension")
|
||||
}
|
||||
|
||||
req.InstancePut.Stateful = snapshot.Stateful
|
||||
req.Stateful = snapshot.Stateful
|
||||
req.Source.Live = false // Snapshots are never running and so we don't need live migration.
|
||||
}
|
||||
|
||||
@@ -1931,7 +1948,10 @@ func (r *ProtocolIncus) CopyInstanceSnapshot(source InstanceServer, instanceName
|
||||
|
||||
targetSecrets := map[string]string{}
|
||||
for k, v := range opAPI.Metadata {
|
||||
targetSecrets[k] = v.(string)
|
||||
val, ok := v.(string)
|
||||
if ok {
|
||||
targetSecrets[k] = val
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the source request
|
||||
@@ -1959,7 +1979,10 @@ func (r *ProtocolIncus) CopyInstanceSnapshot(source InstanceServer, instanceName
|
||||
|
||||
sourceSecrets := map[string]string{}
|
||||
for k, v := range opAPI.Metadata {
|
||||
sourceSecrets[k] = v.(string)
|
||||
val, ok := v.(string)
|
||||
if ok {
|
||||
sourceSecrets[k] = val
|
||||
}
|
||||
}
|
||||
|
||||
// Relay mode migration
|
||||
@@ -1979,7 +2002,10 @@ func (r *ProtocolIncus) CopyInstanceSnapshot(source InstanceServer, instanceName
|
||||
// Extract the websockets
|
||||
targetSecrets := map[string]string{}
|
||||
for k, v := range targetOpAPI.Metadata {
|
||||
targetSecrets[k] = v.(string)
|
||||
val, ok := v.(string)
|
||||
if ok {
|
||||
targetSecrets[k] = val
|
||||
}
|
||||
}
|
||||
|
||||
// Launch the relay
|
||||
@@ -2234,14 +2260,14 @@ func (r *ProtocolIncus) GetInstanceLogfile(name string, filename string) (io.Rea
|
||||
}
|
||||
|
||||
// Prepare the HTTP request
|
||||
url := fmt.Sprintf("%s/1.0%s/%s/logs/%s", r.httpBaseURL.String(), path, url.PathEscape(name), url.PathEscape(filename))
|
||||
uri := fmt.Sprintf("%s/1.0%s/%s/logs/%s", r.httpBaseURL.String(), path, url.PathEscape(name), url.PathEscape(filename))
|
||||
|
||||
url, err = r.setQueryAttributes(url)
|
||||
uri, err = r.setQueryAttributes(uri)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
req, err := http.NewRequest("GET", uri, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -2294,14 +2320,14 @@ func (r *ProtocolIncus) getInstanceExecOutputLogFile(name string, filename strin
|
||||
}
|
||||
|
||||
// Prepare the HTTP request
|
||||
url := fmt.Sprintf("%s/1.0%s/%s/logs/exec-output/%s", r.httpBaseURL.String(), path, url.PathEscape(name), url.PathEscape(filename))
|
||||
uri := fmt.Sprintf("%s/1.0%s/%s/logs/exec-output/%s", r.httpBaseURL.String(), path, url.PathEscape(name), url.PathEscape(filename))
|
||||
|
||||
url, err = r.setQueryAttributes(url)
|
||||
uri, err = r.setQueryAttributes(uri)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
req, err := http.NewRequest("GET", uri, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -2357,8 +2383,8 @@ func (r *ProtocolIncus) GetInstanceMetadata(name string) (*api.ImageMetadata, st
|
||||
|
||||
metadata := api.ImageMetadata{}
|
||||
|
||||
url := fmt.Sprintf("%s/%s/metadata", path, url.PathEscape(name))
|
||||
etag, err := r.queryStruct("GET", url, nil, "", &metadata)
|
||||
uri := fmt.Sprintf("%s/%s/metadata", path, url.PathEscape(name))
|
||||
etag, err := r.queryStruct("GET", uri, nil, "", &metadata)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
@@ -2377,8 +2403,8 @@ func (r *ProtocolIncus) UpdateInstanceMetadata(name string, metadata api.ImageMe
|
||||
return fmt.Errorf("The server is missing the required \"container_edit_metadata\" API extension")
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/%s/metadata", path, url.PathEscape(name))
|
||||
_, _, err = r.query("PUT", url, metadata, ETag)
|
||||
uri := fmt.Sprintf("%s/%s/metadata", path, url.PathEscape(name))
|
||||
_, _, err = r.query("PUT", uri, metadata, ETag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -2399,8 +2425,8 @@ func (r *ProtocolIncus) GetInstanceTemplateFiles(instanceName string) ([]string,
|
||||
|
||||
templates := []string{}
|
||||
|
||||
url := fmt.Sprintf("%s/%s/metadata/templates", path, url.PathEscape(instanceName))
|
||||
_, err = r.queryStruct("GET", url, nil, "", &templates)
|
||||
uri := fmt.Sprintf("%s/%s/metadata/templates", path, url.PathEscape(instanceName))
|
||||
_, err = r.queryStruct("GET", uri, nil, "", &templates)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -2419,14 +2445,14 @@ func (r *ProtocolIncus) GetInstanceTemplateFile(instanceName string, templateNam
|
||||
return nil, fmt.Errorf("The server is missing the required \"container_edit_metadata\" API extension")
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/1.0%s/%s/metadata/templates?path=%s", r.httpBaseURL.String(), path, url.PathEscape(instanceName), url.QueryEscape(templateName))
|
||||
uri := fmt.Sprintf("%s/1.0%s/%s/metadata/templates?path=%s", r.httpBaseURL.String(), path, url.PathEscape(instanceName), url.QueryEscape(templateName))
|
||||
|
||||
url, err = r.setQueryAttributes(url)
|
||||
uri, err = r.setQueryAttributes(uri)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
req, err := http.NewRequest("GET", uri, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -2459,14 +2485,14 @@ func (r *ProtocolIncus) CreateInstanceTemplateFile(instanceName string, template
|
||||
return fmt.Errorf("The server is missing the required \"container_edit_metadata\" API extension")
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/1.0%s/%s/metadata/templates?path=%s", r.httpBaseURL.String(), path, url.PathEscape(instanceName), url.QueryEscape(templateName))
|
||||
uri := fmt.Sprintf("%s/1.0%s/%s/metadata/templates?path=%s", r.httpBaseURL.String(), path, url.PathEscape(instanceName), url.QueryEscape(templateName))
|
||||
|
||||
url, err = r.setQueryAttributes(url)
|
||||
uri, err = r.setQueryAttributes(uri)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", url, content)
|
||||
req, err := http.NewRequest("POST", uri, content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -2553,9 +2579,14 @@ func (r *ProtocolIncus) ConsoleInstance(instanceName string, console api.Instanc
|
||||
|
||||
value, ok := opAPI.Metadata["fds"]
|
||||
if ok {
|
||||
values := value.(map[string]any)
|
||||
for k, v := range values {
|
||||
fds[k] = v.(string)
|
||||
values, ok := value.(map[string]any)
|
||||
if ok {
|
||||
for k, v := range values {
|
||||
val, ok := v.(string)
|
||||
if ok {
|
||||
fds[k] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2645,9 +2676,14 @@ func (r *ProtocolIncus) ConsoleInstanceDynamic(instanceName string, console api.
|
||||
|
||||
value, ok := opAPI.Metadata["fds"]
|
||||
if ok {
|
||||
values := value.(map[string]any)
|
||||
for k, v := range values {
|
||||
fds[k] = v.(string)
|
||||
values, ok := value.(map[string]any)
|
||||
if ok {
|
||||
for k, v := range values {
|
||||
val, ok := v.(string)
|
||||
if ok {
|
||||
fds[k] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2693,7 +2729,7 @@ func (r *ProtocolIncus) ConsoleInstanceDynamic(instanceName string, console api.
|
||||
// GetInstanceConsoleLog requests that Incus attaches to the console device of a instance.
|
||||
//
|
||||
// Note that it's the caller's responsibility to close the returned ReadCloser.
|
||||
func (r *ProtocolIncus) GetInstanceConsoleLog(instanceName string, args *InstanceConsoleLogArgs) (io.ReadCloser, error) {
|
||||
func (r *ProtocolIncus) GetInstanceConsoleLog(instanceName string, _ *InstanceConsoleLogArgs) (io.ReadCloser, error) {
|
||||
path, _, err := r.instanceTypeToPath(api.InstanceTypeAny)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -2704,14 +2740,14 @@ func (r *ProtocolIncus) GetInstanceConsoleLog(instanceName string, args *Instanc
|
||||
}
|
||||
|
||||
// Prepare the HTTP request
|
||||
url := fmt.Sprintf("%s/1.0%s/%s/console", r.httpBaseURL.String(), path, url.PathEscape(instanceName))
|
||||
uri := fmt.Sprintf("%s/1.0%s/%s/console", r.httpBaseURL.String(), path, url.PathEscape(instanceName))
|
||||
|
||||
url, err = r.setQueryAttributes(url)
|
||||
uri, err = r.setQueryAttributes(uri)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
req, err := http.NewRequest("GET", uri, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -2734,7 +2770,7 @@ func (r *ProtocolIncus) GetInstanceConsoleLog(instanceName string, args *Instanc
|
||||
}
|
||||
|
||||
// DeleteInstanceConsoleLog deletes the requested instance's console log.
|
||||
func (r *ProtocolIncus) DeleteInstanceConsoleLog(instanceName string, args *InstanceConsoleLogArgs) error {
|
||||
func (r *ProtocolIncus) DeleteInstanceConsoleLog(instanceName string, _ *InstanceConsoleLogArgs) error {
|
||||
path, _, err := r.instanceTypeToPath(api.InstanceTypeAny)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -85,13 +85,13 @@ func (r *ProtocolIncus) GetNetworkACLLogfile(name string) (io.ReadCloser, error)
|
||||
}
|
||||
|
||||
// Prepare the HTTP request
|
||||
url := fmt.Sprintf("%s/1.0/network-acls/%s/log", r.httpBaseURL.String(), url.PathEscape(name))
|
||||
url, err := r.setQueryAttributes(url)
|
||||
uri := fmt.Sprintf("%s/1.0/network-acls/%s/log", r.httpBaseURL.String(), url.PathEscape(name))
|
||||
uri, err := r.setQueryAttributes(uri)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
req, err := http.NewRequest("GET", uri, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -47,13 +47,12 @@ func (r *ProtocolIncus) GetOIDCTokens() *oidc.Tokens[*oidc.IDTokenClaims] {
|
||||
return r.oidcClient.tokens
|
||||
}
|
||||
|
||||
// Custom transport that modifies requests to inject the audience field.
|
||||
// oidcTransport is a custom HTTP transport that injects the audience field into requests directed at the device authorization endpoint.
|
||||
type oidcTransport struct {
|
||||
deviceAuthorizationEndpoint string
|
||||
audience string
|
||||
}
|
||||
|
||||
// oidcTransport is a custom HTTP transport that injects the audience field into requests directed at the device authorization endpoint.
|
||||
// RoundTrip is a method of oidcTransport that modifies the request, adds the audience parameter if appropriate, and sends it along.
|
||||
func (o *oidcTransport) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||
// Don't modify the request if it's not to the device authorization endpoint, or there are no
|
||||
@@ -255,12 +254,12 @@ func (o *oidcClient) refresh(issuer string, clientID string) error {
|
||||
return errRefreshAccessToken
|
||||
}
|
||||
|
||||
o.tokens.Token.AccessToken = oauthTokens.AccessToken
|
||||
o.tokens.AccessToken = oauthTokens.AccessToken
|
||||
o.tokens.TokenType = oauthTokens.TokenType
|
||||
o.tokens.Expiry = oauthTokens.Expiry
|
||||
|
||||
if oauthTokens.RefreshToken != "" {
|
||||
o.tokens.Token.RefreshToken = oauthTokens.RefreshToken
|
||||
o.tokens.RefreshToken = oauthTokens.RefreshToken
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -312,11 +311,11 @@ func (o *oidcClient) authenticate(issuer string, clientID string, audience strin
|
||||
|
||||
o.tokens.Expiry = time.Now().Add(time.Duration(token.ExpiresIn))
|
||||
o.tokens.IDToken = token.IDToken
|
||||
o.tokens.Token.AccessToken = token.AccessToken
|
||||
o.tokens.AccessToken = token.AccessToken
|
||||
o.tokens.TokenType = token.TokenType
|
||||
|
||||
if token.RefreshToken != "" {
|
||||
o.tokens.Token.RefreshToken = token.RefreshToken
|
||||
o.tokens.RefreshToken = token.RefreshToken
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -192,7 +192,7 @@ func (r *ProtocolIncus) GetMetrics() (string, error) {
|
||||
// ApplyServerPreseed configures a target Incus server with the provided server and cluster configuration.
|
||||
func (r *ProtocolIncus) ApplyServerPreseed(config api.InitPreseed) error {
|
||||
// Apply server configuration.
|
||||
if config.Server.Config != nil && len(config.Server.Config) > 0 {
|
||||
if len(config.Server.Config) > 0 {
|
||||
// Get current config.
|
||||
server, etag, err := r.GetServer()
|
||||
if err != nil {
|
||||
@@ -211,7 +211,7 @@ func (r *ProtocolIncus) ApplyServerPreseed(config api.InitPreseed) error {
|
||||
}
|
||||
|
||||
// Apply storage configuration.
|
||||
if config.Server.StoragePools != nil && len(config.Server.StoragePools) > 0 {
|
||||
if len(config.Server.StoragePools) > 0 {
|
||||
// Get the list of storagePools.
|
||||
storagePoolNames, err := r.GetStoragePoolNames()
|
||||
if err != nil {
|
||||
@@ -330,7 +330,7 @@ func (r *ProtocolIncus) ApplyServerPreseed(config api.InitPreseed) error {
|
||||
}
|
||||
|
||||
// Apply project configuration.
|
||||
if config.Server.Projects != nil && len(config.Server.Projects) > 0 {
|
||||
if len(config.Server.Projects) > 0 {
|
||||
// Get the list of projects.
|
||||
projectNames, err := r.GetProjectNames()
|
||||
if err != nil {
|
||||
@@ -469,8 +469,7 @@ func (r *ProtocolIncus) ApplyServerPreseed(config api.InitPreseed) error {
|
||||
}
|
||||
|
||||
// Apply profile configuration.
|
||||
if config.Server.Profiles != nil && len(config.Server.Profiles) > 0 {
|
||||
|
||||
if len(config.Server.Profiles) > 0 {
|
||||
// Apply profile configuration.
|
||||
applyProfile := func(profile api.InitProfileProjectPost) error {
|
||||
// Get the current profile.
|
||||
@@ -535,7 +534,6 @@ func (r *ProtocolIncus) ApplyServerPreseed(config api.InitPreseed) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -108,12 +108,12 @@ func (r *ProtocolIncus) GetStoragePoolVolumesAllProjects(pool string) ([]api.Sto
|
||||
|
||||
volumes := []api.StorageVolume{}
|
||||
|
||||
url := api.NewURL().Path("storage-pools", pool, "volumes").
|
||||
uri := api.NewURL().Path("storage-pools", pool, "volumes").
|
||||
WithQuery("recursion", "1").
|
||||
WithQuery("all-projects", "true")
|
||||
|
||||
// Fetch the raw value.
|
||||
_, err = r.queryStruct("GET", url.String(), nil, "", &volumes)
|
||||
_, err = r.queryStruct("GET", uri.String(), nil, "", &volumes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -155,13 +155,13 @@ func (r *ProtocolIncus) GetStoragePoolVolumesWithFilterAllProjects(pool string,
|
||||
|
||||
volumes := []api.StorageVolume{}
|
||||
|
||||
url := api.NewURL().Path("storage-pools", pool, "volumes").
|
||||
uri := api.NewURL().Path("storage-pools", pool, "volumes").
|
||||
WithQuery("recursion", "1").
|
||||
WithQuery("filter", parseFilters(filters)).
|
||||
WithQuery("all-projects", "true")
|
||||
|
||||
// Fetch the raw value.
|
||||
_, err = r.queryStruct("GET", url.String(), nil, "", &volumes)
|
||||
_, err = r.queryStruct("GET", uri.String(), nil, "", &volumes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -636,7 +636,10 @@ func (r *ProtocolIncus) CopyStoragePoolVolume(pool string, source InstanceServer
|
||||
|
||||
targetSecrets := map[string]string{}
|
||||
for k, v := range opAPI.Metadata {
|
||||
targetSecrets[k] = v.(string)
|
||||
val, ok := v.(string)
|
||||
if ok {
|
||||
targetSecrets[k] = val
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the source request
|
||||
@@ -666,7 +669,10 @@ func (r *ProtocolIncus) CopyStoragePoolVolume(pool string, source InstanceServer
|
||||
// Prepare source server secrets for remote
|
||||
sourceSecrets := map[string]string{}
|
||||
for k, v := range opAPI.Metadata {
|
||||
sourceSecrets[k] = v.(string)
|
||||
val, ok := v.(string)
|
||||
if ok {
|
||||
sourceSecrets[k] = val
|
||||
}
|
||||
}
|
||||
|
||||
// Relay mode migration
|
||||
@@ -689,7 +695,10 @@ func (r *ProtocolIncus) CopyStoragePoolVolume(pool string, source InstanceServer
|
||||
// Extract the websockets
|
||||
targetSecrets := map[string]string{}
|
||||
for k, v := range targetOpAPI.Metadata {
|
||||
targetSecrets[k] = v.(string)
|
||||
val, ok := v.(string)
|
||||
if ok {
|
||||
targetSecrets[k] = val
|
||||
}
|
||||
}
|
||||
|
||||
// Launch the relay
|
||||
|
||||
@@ -71,7 +71,7 @@ func (r *ProtocolOCI) GetImageFingerprints() ([]string, error) {
|
||||
}
|
||||
|
||||
// GetImagesWithFilter returns a filtered list of available images as Image structs.
|
||||
func (r *ProtocolOCI) GetImagesWithFilter(filters []string) ([]api.Image, error) {
|
||||
func (r *ProtocolOCI) GetImagesWithFilter(_ []string) ([]api.Image, error) {
|
||||
return nil, fmt.Errorf("Can't list images from OCI registry")
|
||||
}
|
||||
|
||||
@@ -320,17 +320,17 @@ func (r *ProtocolOCI) GetImageFile(fingerprint string, req ImageFileRequest) (*I
|
||||
}
|
||||
|
||||
// GetImageSecret isn't relevant for the simplestreams protocol.
|
||||
func (r *ProtocolOCI) GetImageSecret(fingerprint string) (string, error) {
|
||||
func (r *ProtocolOCI) GetImageSecret(_ string) (string, error) {
|
||||
return "", fmt.Errorf("Private images aren't supported with OCI registry")
|
||||
}
|
||||
|
||||
// GetPrivateImage isn't relevant for the simplestreams protocol.
|
||||
func (r *ProtocolOCI) GetPrivateImage(fingerprint string, secret string) (*api.Image, string, error) {
|
||||
func (r *ProtocolOCI) GetPrivateImage(_ string, _ string) (*api.Image, string, error) {
|
||||
return nil, "", fmt.Errorf("Private images aren't supported with OCI registry")
|
||||
}
|
||||
|
||||
// GetPrivateImageFile isn't relevant for the simplestreams protocol.
|
||||
func (r *ProtocolOCI) GetPrivateImageFile(fingerprint string, secret string, req ImageFileRequest) (*ImageFileResponse, error) {
|
||||
func (r *ProtocolOCI) GetPrivateImageFile(_ string, _ string, _ ImageFileRequest) (*ImageFileResponse, error) {
|
||||
return nil, fmt.Errorf("Private images aren't supported with OCI registry")
|
||||
}
|
||||
|
||||
@@ -439,6 +439,6 @@ func (r *ProtocolOCI) GetImageAliasArchitectures(imageType string, name string)
|
||||
}
|
||||
|
||||
// ExportImage exports (copies) an image to a remote server.
|
||||
func (r *ProtocolOCI) ExportImage(fingerprint string, image api.ImageExportPost) (Operation, error) {
|
||||
func (r *ProtocolOCI) ExportImage(_ string, _ api.ImageExportPost) (Operation, error) {
|
||||
return nil, fmt.Errorf("Exporting images is not supported with OCI registry")
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
|
||||
"github.com/lxc/incus/v6/shared/api"
|
||||
"github.com/lxc/incus/v6/shared/logger"
|
||||
"github.com/lxc/incus/v6/shared/simplestreams"
|
||||
"github.com/lxc/incus/v6/shared/subprocess"
|
||||
"github.com/lxc/incus/v6/shared/util"
|
||||
)
|
||||
@@ -54,7 +55,7 @@ func (r *ProtocolSimpleStreams) GetImageFingerprints() ([]string, error) {
|
||||
}
|
||||
|
||||
// GetImagesWithFilter returns a filtered list of available images as Image structs.
|
||||
func (r *ProtocolSimpleStreams) GetImagesWithFilter(filters []string) ([]api.Image, error) {
|
||||
func (r *ProtocolSimpleStreams) GetImagesWithFilter(_ []string) ([]api.Image, error) {
|
||||
return nil, fmt.Errorf("GetImagesWithFilter is not supported by the simplestreams protocol")
|
||||
}
|
||||
|
||||
@@ -160,6 +161,48 @@ func (r *ProtocolSimpleStreams) GetImageFile(fingerprint string, req ImageFileRe
|
||||
downloaded := false
|
||||
_, err := exec.LookPath("xdelta3")
|
||||
if err == nil && req.DeltaSourceRetriever != nil {
|
||||
applyDelta := func(file simplestreams.DownloadableFile, srcPath string, target io.Writer) (int64, error) {
|
||||
// Create temporary file for the delta
|
||||
deltaFile, err := os.CreateTemp("", "incus_image_")
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
defer func() { _ = deltaFile.Close() }()
|
||||
|
||||
defer func() { _ = os.Remove(deltaFile.Name()) }()
|
||||
|
||||
// Download the delta
|
||||
_, err = download(file.Path, "rootfs delta", file.Sha256, deltaFile)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
// Create temporary file for the delta
|
||||
patchedFile, err := os.CreateTemp("", "incus_image_")
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
defer func() { _ = patchedFile.Close() }()
|
||||
|
||||
defer func() { _ = os.Remove(patchedFile.Name()) }()
|
||||
|
||||
// Apply it
|
||||
_, err = subprocess.RunCommand("xdelta3", "-f", "-d", "-s", srcPath, deltaFile.Name(), patchedFile.Name())
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
// Copy to the target
|
||||
size, err := io.Copy(req.RootfsFile, patchedFile)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
return size, nil
|
||||
}
|
||||
|
||||
for filename, file := range files {
|
||||
_, srcFingerprint, prefixFound := strings.Cut(filename, "root.delta-")
|
||||
if !prefixFound {
|
||||
@@ -172,40 +215,7 @@ func (r *ProtocolSimpleStreams) GetImageFile(fingerprint string, req ImageFileRe
|
||||
continue
|
||||
}
|
||||
|
||||
// Create temporary file for the delta
|
||||
deltaFile, err := os.CreateTemp("", "incus_image_")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer func() { _ = deltaFile.Close() }()
|
||||
|
||||
defer func() { _ = os.Remove(deltaFile.Name()) }()
|
||||
|
||||
// Download the delta
|
||||
_, err = download(file.Path, "rootfs delta", file.Sha256, deltaFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create temporary file for the delta
|
||||
patchedFile, err := os.CreateTemp("", "incus_image_")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer func() { _ = patchedFile.Close() }()
|
||||
|
||||
defer func() { _ = os.Remove(patchedFile.Name()) }()
|
||||
|
||||
// Apply it
|
||||
_, err = subprocess.RunCommand("xdelta3", "-f", "-d", "-s", srcPath, deltaFile.Name(), patchedFile.Name())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Copy to the target
|
||||
size, err := io.Copy(req.RootfsFile, patchedFile)
|
||||
size, err := applyDelta(file, srcPath, req.RootfsFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -234,17 +244,17 @@ func (r *ProtocolSimpleStreams) GetImageFile(fingerprint string, req ImageFileRe
|
||||
}
|
||||
|
||||
// GetImageSecret isn't relevant for the simplestreams protocol.
|
||||
func (r *ProtocolSimpleStreams) GetImageSecret(fingerprint string) (string, error) {
|
||||
func (r *ProtocolSimpleStreams) GetImageSecret(_ string) (string, error) {
|
||||
return "", fmt.Errorf("Private images aren't supported by the simplestreams protocol")
|
||||
}
|
||||
|
||||
// GetPrivateImage isn't relevant for the simplestreams protocol.
|
||||
func (r *ProtocolSimpleStreams) GetPrivateImage(fingerprint string, secret string) (*api.Image, string, error) {
|
||||
func (r *ProtocolSimpleStreams) GetPrivateImage(_ string, _ string) (*api.Image, string, error) {
|
||||
return nil, "", fmt.Errorf("Private images aren't supported by the simplestreams protocol")
|
||||
}
|
||||
|
||||
// GetPrivateImageFile isn't relevant for the simplestreams protocol.
|
||||
func (r *ProtocolSimpleStreams) GetPrivateImageFile(fingerprint string, secret string, req ImageFileRequest) (*ImageFileResponse, error) {
|
||||
func (r *ProtocolSimpleStreams) GetPrivateImageFile(_ string, _ string, _ ImageFileRequest) (*ImageFileResponse, error) {
|
||||
return nil, fmt.Errorf("Private images aren't supported by the simplestreams protocol")
|
||||
}
|
||||
|
||||
@@ -315,6 +325,6 @@ func (r *ProtocolSimpleStreams) GetImageAliasArchitectures(imageType string, nam
|
||||
}
|
||||
|
||||
// ExportImage exports (copies) an image to a remote server.
|
||||
func (r *ProtocolSimpleStreams) ExportImage(fingerprint string, image api.ImageExportPost) (Operation, error) {
|
||||
func (r *ProtocolSimpleStreams) ExportImage(_ string, _ api.ImageExportPost) (Operation, error) {
|
||||
return nil, fmt.Errorf("Exporting images is not supported by the simplestreams protocol")
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ func tlsHTTPClient(client *http.Client, tlsClientCert string, tlsClientKey strin
|
||||
// Any errors encountered during the setup process are also handled by the function.
|
||||
func unixHTTPClient(args *ConnectionArgs, path string) (*http.Client, error) {
|
||||
// Setup a Unix socket dialer
|
||||
unixDial := func(_ context.Context, network, addr string) (net.Conn, error) {
|
||||
unixDial := func(_ context.Context, _ string, _ string) (net.Conn, error) {
|
||||
raddr, err := net.ResolveUnixAddr("unix", path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
Reference in New Issue
Block a user