Code

Initial commit for the github.com/sysdb/go Go packages.
authorSebastian Harl <sh@tokkee.org>
Thu, 18 Sep 2014 19:56:39 +0000 (21:56 +0200)
committerSebastian Harl <sh@tokkee.org>
Thu, 18 Sep 2014 19:56:39 +0000 (21:56 +0200)
This is the initial version of core Go bindings for SysDB (https://sysdb.io/).
For now, two packages are provided:

 - github.com/sysdb/go/client: A SysDB client implementation.

 - github.com/sysdb/go/proto: Helper functions for using the SysDB front-end
   protocol. That's the protocol used for communication between a client and a
   SysDB server instance.

COPYING [new file with mode: 0644]
README [new file with mode: 0644]
client/client.go [new file with mode: 0644]
proto/proto.go [new file with mode: 0644]

diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..b7a1f1b
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,24 @@
+Copyright (c) 2014 Sebastian 'tokkee' Harl <sh@tokkee.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..0dbe76d
--- /dev/null
+++ b/README
@@ -0,0 +1,70 @@
+                           Core Go bindings for SysDB
+                          ============================
+
+  The core Go bindings for SysDB are a set of packages for the Go programming
+  language providing core functionality to interact with SysDB.
+
+What is SysDB?
+--------------
+
+  “System DataBase” (SysDB) is a multi-backend system management and inventory
+  collection service. It stores system and inventory information about
+  hardware and software systems. This information is (continuously) collected
+  from various configurable backends (inventory services, monitoring services,
+  etc.) and stored in a graph-like hierarchy of generic objects. The store may
+  be queried through a generic interface independent of the active backends.
+  Object names are canonicalized before they are added to the store to ensure
+  a consistent view of your infrastructure.
+
+  The central object type is a host, which generally represents a physical or
+  virtual machine or any other type of physical resource. Hosts, in turn, may
+  reference a list of services which represent any kind of logical resource
+  like a software system. Both, hosts and services, may reference a list of
+  attributes which represent further information about the respective host or
+  service object. For example, attributes may specify static information like
+  a host's architecture or the software version. A host may also reference a
+  list of metrics which are references to performance data stored about the
+  host. SysDB supports querying the respective time-series from a backend's
+  data store.
+
+  SysDB is free and open source software, licensed under the 2-clause BSD
+  license. See COPYING for details. Changes between all SysDB releases can be
+  found in the file ReleaseNotes.
+
+  <https://sysdb.io/>
+
+Install the Go bindings
+-----------------------
+
+  Installing all of the packages provided by this project is as easy as
+  running the following command:
+
+    go get github.com/sysdb/go/...
+
+  This will download and install the packages and all of their dependencies
+  into GOPATH. See ‘go help get’ for more details. See below for a list of all
+  packages and their descriptions.
+
+Packages
+--------
+
+  * github.com/sysdb/go/client: A SysDB client implementation.
+
+  * github.com/sysdb/go/proto: Helper functions for using the SysDB front-end
+    protocol. That's the protocol used for communication between a client and
+    a SysDB server instance.
+
+Getting Help
+------------
+
+  Various channels for asynchronous and real-time communication with
+  developers and users are available. See <https://sysdb.io/contact/> for
+  details about the mailing list, IRC channel, and social media.
+
+Author
+------
+
+  Sebastian “tokkee” Harl <sh@tokkee.org>
+
+  Want to contribute? Check out the website <https://sysdb.io> for details.
+
diff --git a/client/client.go b/client/client.go
new file mode 100644 (file)
index 0000000..131fdd5
--- /dev/null
@@ -0,0 +1,141 @@
+//
+// Copyright (C) 2014 Sebastian 'tokkee' Harl <sh@tokkee.org>
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/*
+Package client provides a SysDB client implementation.
+
+The Connect function connects to a SysDB server as the specified user:
+
+       c, err := client.Connect("unix:/var/run/sysdbd.sock", "username")
+       if err != nil {
+               // handle error
+       }
+       defer c.Close()
+
+The github.com/sysdb/go/proto package provides support for handling requests
+and responses. Use the Send and Receive functions to communicate with the
+server:
+
+       m := &proto.Message{
+               Type: proto.ConnectionQuery,
+               Raw:  []byte{"LOOKUP hosts MATCHING attribute.architecture = 'amd64';"},
+       }
+       if err := c.Send(m); err != nil {
+               // handle error
+       }
+       m, err := c.Receive()
+       if err != nil {
+               // handle error
+       }
+       if m.Type == proto.ConnectionError {
+               // handle failed query
+       }
+       // ...
+*/
+package client
+
+import (
+       "fmt"
+       "net"
+       "strings"
+
+       "github.com/sysdb/go/proto"
+)
+
+// A Conn is a connection to a SysDB server instance.
+//
+// Multiple goroutines may invoke methods on a Conn simultaneously but since
+// the SysDB protocol requires a strict ordering of request and response
+// messages, the communication with the server will usually happen
+// sequentially.
+type Conn struct {
+       c net.Conn
+}
+
+// Connect sets up a client connection to a SysDB server instance at the
+// specified address using the specified user.
+//
+// The address may be a UNIX domain socket, either prefixed with 'unix:' or
+// specifying an absolute file-system path.
+func Connect(addr, user string) (*Conn, error) {
+       network := "tcp"
+       if strings.HasPrefix(addr, "unix:") {
+               network = "unix"
+               addr = addr[len("unix:"):]
+       } else if addr[0] == '/' {
+               network = "unix"
+       }
+
+       c := &Conn{}
+       var err error
+       if c.c, err = net.Dial(network, addr); err != nil {
+               return nil, err
+       }
+
+       m := &proto.Message{
+               Type: proto.ConnectionStartup,
+               Raw:  []byte(user),
+       }
+       if err := c.Send(m); err != nil {
+               return nil, err
+       }
+
+       m, err = c.Receive()
+       if err != nil {
+               return nil, err
+       }
+       if m.Type == proto.ConnectionError {
+               return nil, fmt.Errorf("failed to startup session: %s", string(m.Raw))
+       }
+       if m.Type != proto.ConnectionOK {
+               return nil, fmt.Errorf("failed to startup session: unsupported")
+       }
+       return c, nil
+}
+
+// Close closes the client connection.
+//
+// Any blocked Send or Receive operations will be unblocked and return errors.
+func (c Conn) Close() { c.c.Close() }
+
+// Send encodes the specified message and sends it to the server.
+//
+// Send operations block until the full message could be written to the
+// underlying sockets. This ensures that server and client don't get out of
+// sync.
+func (c Conn) Send(m *proto.Message) error {
+       return proto.Encode(c.c, m)
+}
+
+// Receive waits for a reply from the server and returns the decoded message.
+//
+// Receive operations block until a full message could be read from the
+// underlying socket. This ensures that server and client don't get out of
+// sync.
+func (c Conn) Receive() (*proto.Message, error) {
+       return proto.Decode(c.c)
+}
+
+// vim: set tw=78 sw=4 sw=4 noexpandtab :
diff --git a/proto/proto.go b/proto/proto.go
new file mode 100644 (file)
index 0000000..5aadf9a
--- /dev/null
@@ -0,0 +1,132 @@
+//
+// Copyright (C) 2014 Sebastian 'tokkee' Harl <sh@tokkee.org>
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Package proto provides helper functions for using the SysDB front-end
+// protocol. That's the protocol used for communication between a client and a
+// SysDB server instance.
+package proto
+
+import (
+       "encoding/binary"
+       "io"
+)
+
+// Network byte order.
+var nbo = binary.BigEndian
+
+// A Status represents the type of a message. The message type describes the
+// current status or state of a connection depending on the context.
+type Status uint32
+
+const (
+       // ConnectionOK indicates that a command was successful.
+       ConnectionOK = Status(0)
+       // ConnectionError indicates that a command has failed.
+       ConnectionError = Status(1)
+       // ConnectionLog indicates an (asynchronous) log message.
+       ConnectionLog = Status(2)
+
+       // ConnectionData indicates a successful query returning data.
+       ConnectionData = Status(100)
+)
+
+const (
+       // ConnectionIdle is the internal state for idle connections.
+       ConnectionIdle = Status(0)
+       // ConnectionPing is the state requesting a connection check.
+       ConnectionPing = Status(1)
+       // ConnectionStartup is the state requesting the setup of a client
+       // connection.
+       ConnectionStartup = Status(2)
+
+       // ConnectionQuery is the state requesting the execution of a query in the
+       // server.
+       ConnectionQuery = Status(3)
+       // ConnectionFetch is the state requesting the execution of the 'FETCH'
+       // command in the server.
+       ConnectionFetch = Status(4)
+       // ConnectionList is the state requesting the execution of the 'LIST'
+       // command in the server.
+       ConnectionList = Status(5)
+       // ConnectionLookup is the state requesting the execution of the 'LOOKUP'
+       // command in the server.
+       ConnectionLookup = Status(6)
+       // ConnectionTimeseries is the state requesting the execution of the
+       // 'TIMESERIES' command in the server.
+       ConnectionTimeseries = Status(7)
+
+       // ConnectionExpr is the internal state for expression parsing.
+       ConnectionExpr = Status(100)
+)
+
+// A Message represents a raw message of the SysDB front-end protocol.
+type Message struct {
+       Type Status
+       Raw  []byte
+}
+
+// Decodes reads a raw message encoded in the SysDB wire format from r. The
+// raw body of the message will still be encoded in the wire format.
+//
+// The reader has to be in blocking mode. Otherwise, the client and server
+// will be out of sync after reading a partial message and cannot recover from
+// that.
+func Decode(r io.Reader) (*Message, error) {
+       var header [8]byte
+       if _, err := io.ReadFull(r, header[:]); err != nil {
+               return nil, err
+       }
+
+       typ := nbo.Uint32(header[:4])
+       l := nbo.Uint32(header[4:])
+       msg := make([]byte, l)
+       if _, err := io.ReadFull(r, msg); err != nil {
+               return nil, err
+       }
+
+       return &Message{Status(typ), msg}, nil
+}
+
+// Encode writes a raw message to w. The raw body of m has to be encoded in
+// the SysDB wire format.
+//
+// The writer has to be in blocking mode. Otherwise, the client and server
+// will be out of sync after writing a partial message and cannot recover from
+// that.
+func Encode(w io.Writer, m *Message) error {
+       var header [8]byte
+       nbo.PutUint32(header[:4], uint32(m.Type))
+       nbo.PutUint32(header[4:], uint32(len(m.Raw)))
+
+       if _, err := io.WriteString(w, string(header[:])); err != nil {
+               return err
+       }
+       if _, err := io.WriteString(w, string(m.Raw)); err != nil {
+               return err
+       }
+       return nil
+}
+
+// vim: set tw=78 sw=4 sw=4 noexpandtab :