The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/6791

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
Based on suggestion from https://discuss.linuxcontainers.org/t/two-suggestions-to-improve-first-impression-with-lxd-3-19/6645 this PR expands the suggests to improve instance name validation error messages to make them more helpful.

Also validates snapshot names.
From 2c911762537cae00fe6409d994a4c8162072279b Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 28 Jan 2020 09:23:29 +0000
Subject: [PATCH 1/4] lxd/container: Removes containerValidName function

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/container.go | 14 --------------
 1 file changed, 14 deletions(-)

diff --git a/lxd/container.go b/lxd/container.go
index e86439c2df..abf949c450 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -53,20 +53,6 @@ func init() {
 
 // Helper functions
 
-func containerValidName(name string) error {
-       if strings.Contains(name, shared.SnapshotDelimiter) {
-               return fmt.Errorf(
-                       "The character '%s' is reserved for snapshots.",
-                       shared.SnapshotDelimiter)
-       }
-
-       if !shared.ValidHostname(name) {
-               return fmt.Errorf("Container name isn't a valid hostname")
-       }
-
-       return nil
-}
-
 // instanceCreateAsEmpty creates an empty instance.
 func instanceCreateAsEmpty(d *Daemon, args db.InstanceArgs) 
(instance.Instance, error) {
        // Create the instance record.

From a8a2612c9f15843e5c8835bbfddfaaa00afbee29 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 28 Jan 2020 09:23:48 +0000
Subject: [PATCH 2/4] lxd/container: Switches to instance.ValidName

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/container.go                    | 15 +++++++--------
 lxd/container_logs.go               | 10 +++++++---
 lxd/container_lxc.go                |  5 +++--
 lxd/containers_post.go              |  5 +++++
 lxd/instance/drivers/driver_qemu.go |  5 +++--
 5 files changed, 25 insertions(+), 15 deletions(-)

diff --git a/lxd/container.go b/lxd/container.go
index abf949c450..844fe79b75 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -672,19 +672,18 @@ func instanceCreateInternal(s *state.State, args 
db.InstanceArgs) (instance.Inst
                args.Architecture = s.OS.Architectures[0]
        }
 
-       // Validate container name if not snapshot (as snapshots use disallowed 
/ char in names).
-       if !args.Snapshot {
-               err := containerValidName(args.Name)
-               if err != nil {
-                       return nil, err
-               }
+       err := instance.ValidName(args.Name, args.Snapshot)
+       if err != nil {
+               return nil, err
+       }
 
-               // Unset expiry date since containers don't expire.
+       if !args.Snapshot {
+               // Unset expiry date since instances don't expire.
                args.ExpiryDate = time.Time{}
        }
 
        // Validate container config.
-       err := instance.ValidConfig(s.OS, args.Config, false, false)
+       err = instance.ValidConfig(s.OS, args.Config, false, false)
        if err != nil {
                return nil, err
        }
diff --git a/lxd/container_logs.go b/lxd/container_logs.go
index dc1355a05c..3c7aef4b24 100644
--- a/lxd/container_logs.go
+++ b/lxd/container_logs.go
@@ -9,6 +9,7 @@ import (
 
        "github.com/gorilla/mux"
 
+       "github.com/lxc/lxd/lxd/instance"
        "github.com/lxc/lxd/lxd/project"
        "github.com/lxc/lxd/lxd/response"
        "github.com/lxc/lxd/shared"
@@ -64,7 +65,8 @@ func containerLogsGet(d *Daemon, r *http.Request) 
response.Response {
                return resp
        }
 
-       if err := containerValidName(name); err != nil {
+       err = instance.ValidName(name, false)
+       if err != nil {
                return response.BadRequest(err)
        }
 
@@ -118,7 +120,8 @@ func containerLogGet(d *Daemon, r *http.Request) 
response.Response {
 
        file := mux.Vars(r)["file"]
 
-       if err := containerValidName(name); err != nil {
+       err = instance.ValidName(name, false)
+       if err != nil {
                return response.BadRequest(err)
        }
 
@@ -154,7 +157,8 @@ func containerLogDelete(d *Daemon, r *http.Request) 
response.Response {
 
        file := mux.Vars(r)["file"]
 
-       if err := containerValidName(name); err != nil {
+       err = instance.ValidName(name, false)
+       if err != nil {
                return response.BadRequest(err)
        }
 
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 0a4497f47e..6e162807b4 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -3625,8 +3625,9 @@ func (c *containerLXC) Rename(newName string) error {
        logger.Info("Renaming container", ctxMap)
 
        // Sanity checks.
-       if !c.IsSnapshot() && !shared.ValidHostname(newName) {
-               return fmt.Errorf("Invalid container name")
+       err := instance.ValidName(newName, c.IsSnapshot())
+       if err != nil {
+               return err
        }
 
        if c.IsRunning() {
diff --git a/lxd/containers_post.go b/lxd/containers_post.go
index f78781b903..376261d49e 100644
--- a/lxd/containers_post.go
+++ b/lxd/containers_post.go
@@ -58,6 +58,11 @@ func createFromImage(d *Daemon, project string, req 
*api.InstancesPost) response
                        Profiles:    req.Profiles,
                }
 
+               err := instance.ValidName(args.Name, args.Snapshot)
+               if err != nil {
+                       return err
+               }
+
                var info *api.Image
                if req.Source.Server != "" {
                        autoUpdate, err := cluster.ConfigGetBool(d.cluster, 
"images.auto_update_cached")
diff --git a/lxd/instance/drivers/driver_qemu.go 
b/lxd/instance/drivers/driver_qemu.go
index fb13696a57..33cd43f8c6 100644
--- a/lxd/instance/drivers/driver_qemu.go
+++ b/lxd/instance/drivers/driver_qemu.go
@@ -1794,8 +1794,9 @@ func (vm *qemu) Rename(newName string) error {
        logger.Info("Renaming instance", ctxMap)
 
        // Sanity checks.
-       if !vm.IsSnapshot() && !shared.ValidHostname(newName) {
-               return fmt.Errorf("Invalid instance name")
+       err := instance.ValidName(newName, vm.IsSnapshot())
+       if err != nil {
+               return err
        }
 
        if vm.IsRunning() {

From 853816a166c049e6a6d40a536314b3f5543c43f9 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 28 Jan 2020 09:24:40 +0000
Subject: [PATCH 3/4] lxd/instance/instance/utils: Adds ValidName function

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/instance/instance_utils.go | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/lxd/instance/instance_utils.go b/lxd/instance/instance_utils.go
index 4fa6984ef6..3293e01478 100644
--- a/lxd/instance/instance_utils.go
+++ b/lxd/instance/instance_utils.go
@@ -872,3 +872,18 @@ func SuitableArchitectures(s *state.State, project string, 
req api.InstancesPost
        // No other known types
        return nil, fmt.Errorf("Unknown instance source type: %s", 
req.Source.Type)
 }
+
+// ValidName validates an instance name. There are different validation rules 
for instance snapshot names
+// so it takes an argument indicating whether the name is to be used for a 
snapshot or not.
+func ValidName(instanceName string, isSnapshot bool) error {
+       if !isSnapshot && strings.Contains(instanceName, 
shared.SnapshotDelimiter) {
+               return fmt.Errorf("The character %q is reserved for snapshots", 
shared.SnapshotDelimiter)
+       }
+
+       err := shared.ValidHostname(instanceName)
+       if err != nil {
+               return errors.Wrap(err, "Invalid instance name")
+       }
+
+       return nil
+}

From 06cb1e7edb19614bdd01d6d7b11489cabdebec80 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 28 Jan 2020 09:25:43 +0000
Subject: [PATCH 4/4] shared/util: Modifies ValidHostname to return specific
 error

This makes the error messages more helpful to users.

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 shared/util.go | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/shared/util.go b/shared/util.go
index 0a80f5dd7e..43b11b495c 100644
--- a/shared/util.go
+++ b/shared/util.go
@@ -647,33 +647,34 @@ func RunningInUserNS() bool {
        return true
 }
 
-func ValidHostname(name string) bool {
+// ValidHostname checks the string is valid DNS hostname.
+func ValidHostname(name string) error {
        // Validate length
        if len(name) < 1 || len(name) > 63 {
-               return false
+               return fmt.Errorf("Name must be 1-63 characters long")
        }
 
        // Validate first character
        if strings.HasPrefix(name, "-") {
-               return false
+               return fmt.Errorf(`Name must not start with "-" character`)
        }
 
        if _, err := strconv.Atoi(string(name[0])); err == nil {
-               return false
+               return fmt.Errorf("Name must not be a number")
        }
 
        // Validate last character
        if strings.HasSuffix(name, "-") {
-               return false
+               return fmt.Errorf(`Name must not end with "-" character`)
        }
 
        // Validate the character set
        match, _ := regexp.MatchString("^[-a-zA-Z0-9]*$", name)
        if !match {
-               return false
+               return fmt.Errorf("Name can only contain alphanumeric and 
hyphen characters")
        }
 
-       return true
+       return nil
 }
 
 // Spawn the editor with a temporary YAML file for editing configs
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to