daemon

package
v0.1.26 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 16, 2019 License: Apache-2.0 Imports: 29 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	SlangVersion string

	// Root defines a single instance of our user as we currently do not have
	// I use that to get the rest of the code to think about multi tenancy
	Root = &UserID{0}
)
View Source
var DefinitionService = &Service{map[string]*Endpoint{
	"/": {func(w http.ResponseWriter, r *http.Request) {
		st := GetStorage(r)
		type blueprintJSON struct {
			Def  core.Blueprint `json:"def"`
			Type string         `json:"type"`
		}

		type outJSON struct {
			Objects []blueprintJSON `json:"objects"`
			Status  string          `json:"status"`
			Error   *Error          `json:"error,omitempty"`
		}

		var dataOut outJSON
		var err error
		blueprints := make([]blueprintJSON, 0)

		opIds, err := st.List()

		if err == nil {
			builtinOpIds := elem.GetBuiltinIds()

			for _, opId := range builtinOpIds {
				blueprint, err := elem.GetBlueprint(opId)

				if err != nil {
					break
				}

				blueprints = append(blueprints, blueprintJSON{
					Type: "elementary",
					Def:  *blueprint,
				})
			}

			if err == nil {

				for _, opId := range opIds {
					blueprint, err := st.Load(opId)
					if err != nil {
						continue
					}

					opType := "library"
					if st.IsSavedInWritableBackend(opId) {
						opType = "local"
					}

					blueprints = append(blueprints, blueprintJSON{
						Type: opType,
						Def:  *blueprint,
					})
				}
			}
		}

		if err == nil {
			dataOut = outJSON{Status: "success", Objects: blueprints}
		} else {
			dataOut = outJSON{Status: "error", Error: &Error{Msg: err.Error(), Code: "E000X"}}
		}

		w.WriteHeader(200)
		err = writeJSON(w, dataOut)
		if err != nil {
			log.Print(err)
		}
	}},
	"/def/": {func(w http.ResponseWriter, r *http.Request) {
		st := GetStorage(r)
		fail := func(err *Error) {
			sendFailure(w, &responseBad{err})
		}

		if r.Method == "POST" {
			body, err := ioutil.ReadAll(r.Body)
			if err != nil {
				fail(&Error{Msg: err.Error(), Code: "E000X"})
				return
			}

			var def core.Blueprint
			err = json.Unmarshal(body, &def)
			if err != nil {
				fail(&Error{Msg: err.Error(), Code: "E000X"})
				return
			}

			_, err = st.Save(def)

			if err != nil {
				fail(&Error{Msg: err.Error(), Code: "E000X"})
				return
			}

			sendSuccess(w, nil)
		}
	}},
}}
View Source
var InstanceService = &Service{map[string]*Endpoint{
	"/": {func(w http.ResponseWriter, r *http.Request) {

		type outJSON struct {
			Objects []runningOperator `json:"objects"`
			Status  string            `json:"status"`
			Error   *Error            `json:"error,omitempty"`
		}

		if r.Method == "GET" {
			writeJSON(w, funk.Values(runningOperators.ops))
		}
	}},
}}
View Source
var RunnerService = &Service{map[string]*Endpoint{
	"/": {Handle: func(w http.ResponseWriter, r *http.Request) {
		hub := GetHub(r)
		st := GetStorage(r)
		if r.Method == "POST" {
			var data RunState
			var ri RunInstruction

			decoder := json.NewDecoder(r.Body)
			err := decoder.Decode(&ri)
			if err != nil {
				data = RunState{Status: "error", Error: &Error{Msg: err.Error(), Code: "E000X"}}
				writeJSON(w, &data)
				return
			}

			opId := ri.Id
			op, err := api.BuildAndCompile(opId, ri.Gens, ri.Props, st)
			if err != nil {
				data = RunState{Status: "error", Error: &Error{Msg: err.Error(), Code: "E000X"}}
				writeJSON(w, &data)
				return
			}

			runOp := runningOperators.Run(op)

			go func() {
			loop:
				for {
					select {
					case outgoing := <-runOp.outgoing:

						hub.broadCastTo(Root, Port, outgoing)
					case <-runOp.outStop:
						break loop
					}
				}
			}()

			data.Status = "success"
			data.Handle = runOp.Handle
			data.URL = runOp.URL

			writeJSON(w, &data)

		} else if r.Method == "DELETE" {
			type stopInstructionJSON struct {
				Handle string `json:"handle"`
			}

			type outJSON struct {
				Status string `json:"status"`
				Error  *Error `json:"error,omitempty"`
			}

			var data outJSON

			decoder := json.NewDecoder(r.Body)
			var si stopInstructionJSON
			err := decoder.Decode(&si)
			if err != nil {
				data = outJSON{Status: "error", Error: &Error{Msg: err.Error(), Code: "E000X"}}
				writeJSON(w, &data)
				return
			}

			if err := runningOperators.Halt(si.Handle); err == nil {
				data.Status = "success"
			} else {
				data = outJSON{Status: "error", Error: &Error{Msg: "Unknown handle", Code: "E000X"}}
			}

			writeJSON(w, &data)
		}
	}},
}}
View Source
var RunningInstanceService = &Service{map[string]*Endpoint{
	"/{handle:\\w+}/": {func(w http.ResponseWriter, r *http.Request) {
		handle := mux.Vars(r)["handle"]

		runningIns, err := runningOperators.Get(handle)
		if err != nil {
			w.WriteHeader(404)
			return
		}

		var idat interface{}
		if r.Method == "POST" {
			r.ParseForm()
			buf := new(bytes.Buffer)
			buf.ReadFrom(r.Body)

			if buf.Len() > 0 {
				err := json.Unmarshal(buf.Bytes(), &idat)
				if err != nil {
					w.WriteHeader(400)
					return
				}
			}
			runningIns.incoming <- idat

			writeJSON(w, &runningIns)
		}

	}},
}}
View Source
var SharingService = &Service{map[string]*Endpoint{
	"/export": {func(w http.ResponseWriter, r *http.Request) {
		fail := func(err *Error) {
			sendFailure(w, &responseBad{err})
		}

		if r.Method == "GET" {
			opId, err := uuid.Parse(r.FormValue("id"))

			if err != nil {
				fail(&Error{Msg: err.Error(), Code: "E000X"})
				return
			}

			buf := new(bytes.Buffer)
			zipWriter := zip.NewWriter(buf)

			fileWriter, _ := zipWriter.Create("manifest.yaml")
			manifestBytes, _ := yaml.Marshal(&manifest{
				SlangVersion: SlangVersion,
				TimeUnix:     time.Now().Unix(),
			})

			fileWriter.Write(manifestBytes)

			zipWriter.Close()

			w.Header().Set("Pragma", "public")
			w.Header().Set("Expires", "0")
			w.Header().Set("Cache-Control", "must-revalidate, post-check=0, pre-check=0")
			w.Header().Set("Cache-Control", "public")
			w.Header().Set("Content-Description", "File Transfer")
			w.Header().Set("Content-Type", "application/octet-stream")
			w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s.zip\"", opId))
			w.Header().Set("Content-Transfer-Encoding", "binary")
			w.Header().Set("Content-Length", fmt.Sprintf("%d", len(buf.Bytes())))
			w.Write(buf.Bytes())
		}
	}},
	"/import": {func(w http.ResponseWriter, r *http.Request) {
		fail := func(err *Error) {
			sendFailure(w, &responseBad{err})
		}

		if r.Method == "POST" {
			var buf bytes.Buffer
			file, header, err := r.FormFile("file")
			if err != nil {
				fail(&Error{Msg: err.Error(), Code: "E000X"})
				return
			}
			defer file.Close()

			io.Copy(&buf, file)

			zipReader, err := zip.NewReader(file, header.Size)
			if err != nil {
				fail(&Error{Msg: err.Error(), Code: "E000X"})
				return
			}

			manifest := manifest{}
			for _, file := range zipReader.File {
				if file.Name == "manifest.yaml" {
					fileReader, _ := file.Open()
					buf := new(bytes.Buffer)
					buf.ReadFrom(fileReader)
					yaml.Unmarshal(buf.Bytes(), &manifest)
					fileReader.Close()
				}
			}

			myVersion, err := version.NewVersion(SlangVersion)
			if err == nil {
				manifestVersion, err := version.NewVersion(manifest.SlangVersion)
				if err == nil {
					if myVersion.LessThan(manifestVersion) {
						fail(&Error{Msg: "Please upgrade your slang version", Code: "E000X"})
						return
					}
				}
			}

			fail(&Error{Msg: "not implemented yet", Code: "E000X"})
			return
		}
	}},
}}

Functions

func GetStorage added in v0.1.17

func GetStorage(r *http.Request) storage.Storage

func IsDir added in v0.1.17

func IsDir(p string) bool

func IsDirEmpty

func IsDirEmpty(dir string) bool

func IsNewestSlangVersion added in v0.1.5

func IsNewestSlangVersion(myVerStr string) (bool, string, error)

func SetHub added in v0.1.17

func SetHub(ctx context.Context, h *Hub) context.Context

func SetStorage added in v0.1.17

func SetStorage(ctx context.Context, st *storage.Storage) context.Context

Types

type ConnectedClient added in v0.1.17

type ConnectedClient struct {
	// contains filtered or unexported fields
}

ConnectedClient holds everything we need to know about a connection that was made with a websocket

type Endpoint

type Endpoint struct {
	Handle func(w http.ResponseWriter, r *http.Request)
}

type Error

type Error struct {
	Msg  string `json:"msg"`
	Code string `json:"code"`
}

type Hub added in v0.1.17

type Hub struct {
	// contains filtered or unexported fields
}

Hub maintains the set of active clients and broadcasts messages to the clients.

func GetHub added in v0.1.17

func GetHub(r *http.Request) *Hub

type RunInstruction added in v0.1.17

type RunInstruction struct {
	Id     uuid.UUID       `json:"id"`
	Props  core.Properties `json:"props"`
	Gens   core.Generics   `json:"gens"`
	Stream bool            `json:"stream"`
}

type RunState added in v0.1.17

type RunState struct {
	Handle string `json:"handle,omitempty"`
	URL    string `json:"url,omitempty"`
	Status string `json:"status"`
	Error  *Error `json:"error,omitempty"`
}

type Server

type Server struct {
	Host string
	Port int
	// contains filtered or unexported fields
}

func NewServer added in v0.1.17

func NewServer(ctx *context.Context, env *env.Environment) *Server

func (*Server) AddRedirect

func (s *Server) AddRedirect(path string, redirectTo string)

func (*Server) AddService

func (s *Server) AddService(pathPrefix string, services *Service)

func (*Server) AddStaticServer

func (s *Server) AddStaticServer(pathPrefix string, directory http.Dir)

func (*Server) AddWebsocket added in v0.1.17

func (s *Server) AddWebsocket(path string)

func (*Server) Handler added in v0.1.17

func (s *Server) Handler() http.Handler

func (*Server) Run

func (s *Server) Run() error

type Service

type Service struct {
	Routes map[string]*Endpoint
}

type SlangComponentLoader

type SlangComponentLoader struct {
	// contains filtered or unexported fields
}

func NewComponentLoaderLatestMaster

func NewComponentLoaderLatestMaster(repo string, path string) *SlangComponentLoader

func NewComponentLoaderLatestRelease

func NewComponentLoaderLatestRelease(repo string, path string) *SlangComponentLoader

func (*SlangComponentLoader) GetLatestReleaseVersion

func (dl *SlangComponentLoader) GetLatestReleaseVersion() *version.Version

func (*SlangComponentLoader) GetLocalReleaseVersion

func (dl *SlangComponentLoader) GetLocalReleaseVersion() *version.Version

func (*SlangComponentLoader) Load

func (dl *SlangComponentLoader) Load() error

* Downloads & unpacks latest version of a component.

func (*SlangComponentLoader) NewerVersionExists

func (dl *SlangComponentLoader) NewerVersionExists() bool

type Topic added in v0.1.17

type Topic int

We want types around the topic as this makes it easier to work with. A Topic in this case is meant for easier distinction of what type of message is being send. Basically we attach type information for the other end of the connected client.

const (
	Port     Topic = iota
	Operator       // currently unused but displays the intended usage
)

func (Topic) MarshalJSON added in v0.1.17

func (t Topic) MarshalJSON() ([]byte, error)

This encodes a `Topic` to Json using it's string representation

func (Topic) String added in v0.1.17

func (t Topic) String() string

Since we can't send proper type information over the wire, we send a string representation instead.

type UserID added in v0.1.17

type UserID struct {
	// contains filtered or unexported fields
}

UserID represents an Identifier for a user of the system This is also intended to deliver `envelops` to the correct `ConnectedClients` instead of sending a message to all connected clients. Currently we do not have real users. The variable acts more as a placeholder and thinking vehicle to remind oneself that the system might have more than one user in the future - I know, YAGNI.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL