From 78b40626e68a627eb5082cce2d4df47900efe024 Mon Sep 17 00:00:00 2001 From: ston1th Date: Fri, 10 Dec 2021 20:33:20 +0100 Subject: [PATCH] added better id handling --- node.go | 35 ++++++++++++++++++++++------------- pool.go | 27 +++++++++++++++++---------- scheme.go | 13 ++++++++++++- server.go | 35 ++++++++++++++++++++++++++--------- 4 files changed, 77 insertions(+), 33 deletions(-) diff --git a/node.go b/node.go index 8490464..2251970 100644 --- a/node.go +++ b/node.go @@ -10,10 +10,10 @@ import ( ) var ( - ErrNodesOffline = errors.New("one or more nodes are offline") - ErrNodesNotSearched = errors.New("one or more nodes could not be searched") - ErrEmptyID = errors.New("id is empty") - ErrUnschedulable = errors.New("no schedulable node found") + ErrNodesOffline = errors.New("one or more nodes are offline") + ErrNodesNotSearched = errors.New("one or more nodes could not be searched") + ErrUnschedulable = errors.New("no schedulable node found") + ErrTooManyServersFound = errors.New("too many servers found with the same name") ) type NodeStatus string @@ -205,13 +205,16 @@ func (c *NodeClient) ListServers(ctx context.Context, n *Node) (sl ServerRefList return } -func (c *NodeClient) FindServer(ctx context.Context, name string, id int) (s *ServerRef, err error) { +func (c *NodeClient) FindServer(ctx context.Context, name string, id int) (ref *ServerRef, err error) { + valid := ValidateID(id) == nil nl, err := c.List(ctx) if err != nil { return } - nodeOffline := false - nodeNotSearched := false + var ( + nodeOffline bool + nodeNotSearched bool + ) for _, node := range nl { if node.Status != NodeStatusOnline { nodeOffline = true @@ -223,11 +226,14 @@ func (c *NodeClient) FindServer(ctx context.Context, name string, id int) (s *Se continue } for _, s := range sl { - if id != -1 && s.ID == id { + if valid && s.ID == id { return s, nil } if name != "" && s.Name == name { - return s, nil + if ref != nil { + return nil, ErrTooManyServersFound + } + ref = s } } } @@ -237,16 +243,19 @@ func (c *NodeClient) FindServer(ctx context.Context, name string, id int) (s *Se if nodeNotSearched { return nil, ErrNodesNotSearched } - return nil, ErrServerNotFound + if ref == nil { + err = ErrServerNotFound + } + return } func (c *NodeClient) FindServerByName(ctx context.Context, name string) (s *ServerRef, err error) { - return c.FindServer(ctx, name, -1) + return c.FindServer(ctx, name, InvalidID) } func (c *NodeClient) FindServerByID(ctx context.Context, id int) (s *ServerRef, err error) { - if id == -1 { - err = ErrEmptyID + err = ValidateID(id) + if err != nil { return } return c.FindServer(ctx, "", id) diff --git a/pool.go b/pool.go index 228c948..9bcad91 100644 --- a/pool.go +++ b/pool.go @@ -132,7 +132,8 @@ func (c *PoolClient) ListMembers(ctx context.Context, name string) (sl ServerRef return } -func (c *PoolClient) FindServer(ctx context.Context, poolname, servername string, id int) (s *ServerRef, err error) { +func (c *PoolClient) FindServer(ctx context.Context, poolname, servername string, id int) (ref *ServerRef, err error) { + valid := ValidateID(id) == nil var pools []string if poolname != "" { pools = append(pools, poolname) @@ -147,22 +148,28 @@ func (c *PoolClient) FindServer(ctx context.Context, poolname, servername string if err != nil { return nil, err } - for _, srv := range sl { - if id != -1 && srv.ID == id { - srv.Pool = pool - return srv, nil + for _, s := range sl { + if valid && s.ID == id { + s.Pool = pool + return s, nil } - if servername != "" && srv.Name == servername { - srv.Pool = pool - return srv, nil + if servername != "" && s.Name == servername { + if ref != nil { + return nil, ErrTooManyServersFound + } + s.Pool = pool + ref = s } } } - return nil, ErrServerNotFound + if ref == nil { + err = ErrServerNotFound + } + return } func (c *PoolClient) FindServerByName(ctx context.Context, poolname, servername string) (s *ServerRef, err error) { - return c.FindServer(ctx, poolname, servername, -1) + return c.FindServer(ctx, poolname, servername, InvalidID) } func (c *PoolClient) FindServerByID(ctx context.Context, poolname string, id int) (s *ServerRef, err error) { diff --git a/scheme.go b/scheme.go index 9e8062d..2926628 100644 --- a/scheme.go +++ b/scheme.go @@ -13,14 +13,25 @@ import ( const ( PVEScheme = "pve" PVESchemeURL = PVEScheme + "://" + + MinID = 100 + InvalidID = 0 ) var ( ErrInvalidPVEURL = errors.New("invalid pve url scheme") ErrNoID = errors.New("missing id in url") + ErrInvalidID = errors.New("invalid id") ErrParsingID = errors.New("error parsing id in url") ) +func ValidateID(id int) error { + if id < MinID { + return ErrInvalidID + } + return nil +} + func ParseURL(s string) (pool, node string, id int, err error) { u, err := url.Parse(s) if err != nil { @@ -43,7 +54,7 @@ func ParseURL(s string) (pool, node string, id int, err error) { if err != nil { err = ErrParsingID } - return u.Host, a[1], id, nil + return u.Host, a[1], id, ValidateID(id) } func ServerRefFromURL(s string) (ref *ServerRef, err error) { diff --git a/server.go b/server.go index 77117be..d7bc902 100644 --- a/server.go +++ b/server.go @@ -84,10 +84,11 @@ func (s *Server) Ref() *ServerRef { type ServerRefList []*ServerRef type ServerRef struct { - ID int `json:"vmid"` - Name string `json:"name"` - Node string - Pool string + ID int `json:"vmid"` + Name string `json:"name"` + Template int `json:"template,omitempty"` + Node string `json:"node,omitempty"` + Pool string `json:"pool,omitempty"` } func (ref *ServerRef) InstanceID() string { @@ -98,6 +99,10 @@ func (ref *ServerRef) K8sID() string { return NewURL(ref.Pool, "", ref.ID) } +func (ref *ServerRef) IsTemplate() bool { + return ref.Template == 1 +} + type Resources struct { Cores Cores `json:"cores"` Memory Memory `json:"memory"` @@ -221,7 +226,7 @@ type ServerClient struct { } func (c *ServerClient) NextID(ctx context.Context) (id int, err error) { - id = -1 + id = InvalidID req, err := c.client.NewRequest(ctx, "GET", "/cluster/nextid", nil) if err != nil { return @@ -289,8 +294,9 @@ func (c *ServerClient) GetByURL(ctx context.Context, url string) (s *Server, err } type ServerTemplateOpts struct { - Name string - TemplateID int + Name string + TemplateID int + TemplateName string // TemplateNode is optional TemplateNode string Pool string @@ -302,8 +308,19 @@ func (o *ServerTemplateOpts) Validate(ctx context.Context, c *Client) error { if o.Name == "" { return errors.New("missing name") } - if o.TemplateID <= 0 { - return errors.New("missing template id") + if ValidateID(o.TemplateID) != nil { + if o.TemplateName == "" { + return errors.New("missing or invalid template id") + } + ref, err := c.Node.FindServerByName(ctx, o.TemplateName) + if err != nil { + return fmt.Errorf("template id not found: %w", err) + } + if !ref.IsTemplate() { + return errors.New("server is not a vm template") + } + o.TemplateID = ref.ID + o.TemplateNode = ref.Node } if o.TemplateNode == "" { ref, err := c.Node.FindServerByID(ctx, o.TemplateID)