added better id handling

This commit is contained in:
ston1th 2021-12-10 20:33:20 +01:00
commit 78b40626e6
4 changed files with 77 additions and 33 deletions

35
node.go
View file

@ -10,10 +10,10 @@ import (
) )
var ( var (
ErrNodesOffline = errors.New("one or more nodes are offline") ErrNodesOffline = errors.New("one or more nodes are offline")
ErrNodesNotSearched = errors.New("one or more nodes could not be searched") ErrNodesNotSearched = errors.New("one or more nodes could not be searched")
ErrEmptyID = errors.New("id is empty") ErrUnschedulable = errors.New("no schedulable node found")
ErrUnschedulable = errors.New("no schedulable node found") ErrTooManyServersFound = errors.New("too many servers found with the same name")
) )
type NodeStatus string type NodeStatus string
@ -205,13 +205,16 @@ func (c *NodeClient) ListServers(ctx context.Context, n *Node) (sl ServerRefList
return 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) nl, err := c.List(ctx)
if err != nil { if err != nil {
return return
} }
nodeOffline := false var (
nodeNotSearched := false nodeOffline bool
nodeNotSearched bool
)
for _, node := range nl { for _, node := range nl {
if node.Status != NodeStatusOnline { if node.Status != NodeStatusOnline {
nodeOffline = true nodeOffline = true
@ -223,11 +226,14 @@ func (c *NodeClient) FindServer(ctx context.Context, name string, id int) (s *Se
continue continue
} }
for _, s := range sl { for _, s := range sl {
if id != -1 && s.ID == id { if valid && s.ID == id {
return s, nil return s, nil
} }
if name != "" && s.Name == name { 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 { if nodeNotSearched {
return nil, ErrNodesNotSearched 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) { 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) { func (c *NodeClient) FindServerByID(ctx context.Context, id int) (s *ServerRef, err error) {
if id == -1 { err = ValidateID(id)
err = ErrEmptyID if err != nil {
return return
} }
return c.FindServer(ctx, "", id) return c.FindServer(ctx, "", id)

27
pool.go
View file

@ -132,7 +132,8 @@ func (c *PoolClient) ListMembers(ctx context.Context, name string) (sl ServerRef
return 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 var pools []string
if poolname != "" { if poolname != "" {
pools = append(pools, poolname) pools = append(pools, poolname)
@ -147,22 +148,28 @@ func (c *PoolClient) FindServer(ctx context.Context, poolname, servername string
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, srv := range sl { for _, s := range sl {
if id != -1 && srv.ID == id { if valid && s.ID == id {
srv.Pool = pool s.Pool = pool
return srv, nil return s, nil
} }
if servername != "" && srv.Name == servername { if servername != "" && s.Name == servername {
srv.Pool = pool if ref != nil {
return srv, 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) { 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) { func (c *PoolClient) FindServerByID(ctx context.Context, poolname string, id int) (s *ServerRef, err error) {

View file

@ -13,14 +13,25 @@ import (
const ( const (
PVEScheme = "pve" PVEScheme = "pve"
PVESchemeURL = PVEScheme + "://" PVESchemeURL = PVEScheme + "://"
MinID = 100
InvalidID = 0
) )
var ( var (
ErrInvalidPVEURL = errors.New("invalid pve url scheme") ErrInvalidPVEURL = errors.New("invalid pve url scheme")
ErrNoID = errors.New("missing id in url") ErrNoID = errors.New("missing id in url")
ErrInvalidID = errors.New("invalid id")
ErrParsingID = errors.New("error parsing id in url") 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) { func ParseURL(s string) (pool, node string, id int, err error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
@ -43,7 +54,7 @@ func ParseURL(s string) (pool, node string, id int, err error) {
if err != nil { if err != nil {
err = ErrParsingID 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) { func ServerRefFromURL(s string) (ref *ServerRef, err error) {

View file

@ -84,10 +84,11 @@ func (s *Server) Ref() *ServerRef {
type ServerRefList []*ServerRef type ServerRefList []*ServerRef
type ServerRef struct { type ServerRef struct {
ID int `json:"vmid"` ID int `json:"vmid"`
Name string `json:"name"` Name string `json:"name"`
Node string Template int `json:"template,omitempty"`
Pool string Node string `json:"node,omitempty"`
Pool string `json:"pool,omitempty"`
} }
func (ref *ServerRef) InstanceID() string { func (ref *ServerRef) InstanceID() string {
@ -98,6 +99,10 @@ func (ref *ServerRef) K8sID() string {
return NewURL(ref.Pool, "", ref.ID) return NewURL(ref.Pool, "", ref.ID)
} }
func (ref *ServerRef) IsTemplate() bool {
return ref.Template == 1
}
type Resources struct { type Resources struct {
Cores Cores `json:"cores"` Cores Cores `json:"cores"`
Memory Memory `json:"memory"` Memory Memory `json:"memory"`
@ -221,7 +226,7 @@ type ServerClient struct {
} }
func (c *ServerClient) NextID(ctx context.Context) (id int, err error) { 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) req, err := c.client.NewRequest(ctx, "GET", "/cluster/nextid", nil)
if err != nil { if err != nil {
return return
@ -289,8 +294,9 @@ func (c *ServerClient) GetByURL(ctx context.Context, url string) (s *Server, err
} }
type ServerTemplateOpts struct { type ServerTemplateOpts struct {
Name string Name string
TemplateID int TemplateID int
TemplateName string
// TemplateNode is optional // TemplateNode is optional
TemplateNode string TemplateNode string
Pool string Pool string
@ -302,8 +308,19 @@ func (o *ServerTemplateOpts) Validate(ctx context.Context, c *Client) error {
if o.Name == "" { if o.Name == "" {
return errors.New("missing name") return errors.New("missing name")
} }
if o.TemplateID <= 0 { if ValidateID(o.TemplateID) != nil {
return errors.New("missing template id") 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 == "" { if o.TemplateNode == "" {
ref, err := c.Node.FindServerByID(ctx, o.TemplateID) ref, err := c.Node.FindServerByID(ctx, o.TemplateID)