daemon

package
v0.1.10 Latest Latest
Warning

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

Go to latest
Published: Oct 17, 2018 License: Apache-2.0 Imports: 27 Imported by: 1

Documentation

Index

Constants

View Source
const SuffixPacked = "_packed"
View Source
const SuffixVisual = "_visual"

Variables

View Source
var DefinitionService = &Service{map[string]*Endpoint{
	"/": {func(e *api.Environ, w http.ResponseWriter, r *http.Request) {
		type operatorDefJSON struct {
			Name string           `json:"name"`
			Def  core.OperatorDef `json:"def"`
			Type string           `json:"type"`
		}

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

		var dataOut outJSON
		var opDefList []operatorDefJSON
		var err error

		opNames, err := e.ListOperatorNames()

		if err == nil {
			builtinOpNames := elem.GetBuiltinNames()

			for _, opFQName := range builtinOpNames {
				opDef, err := elem.GetOperatorDef(opFQName)

				if err != nil {
					break
				}

				opDefList = append(opDefList, operatorDefJSON{
					Name: opFQName,
					Type: "elementary",
					Def:  opDef,
				})
			}

			if err == nil {

				for _, opFQName := range opNames {
					opDefFilePath, _, err := e.GetFilePathWithFileEnding(strings.Replace(opFQName, ".", string(filepath.Separator), -1), "")

					if err != nil {
						continue
					}

					opDef, err := e.ReadOperatorDef(opDefFilePath, nil)
					if err != nil {
						continue
					}

					opType := "library"
					if e.IsLocalOperator(opFQName) {
						opType = "local"
					}

					opDefList = append(opDefList, operatorDefJSON{
						Name: opFQName,
						Type: opType,
						Def:  opDef,
					})
				}
			}
		}

		if err == nil {
			dataOut = outJSON{Status: "success", Objects: opDefList}
		} 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(e *api.Environ, w http.ResponseWriter, r *http.Request) {
		fail := func(err *Error) {
			sendFailure(w, &responseBad{err})
		}

		if r.Method == "POST" {

			cwd := e.WorkingDir()
			opFQName := r.FormValue("fqop")

			if !checkOperatorNameIsValid(opFQName) {
				fail(&Error{Msg: fmt.Sprintf("operator must start with capital letter and may only contain alphanumerics"), Code: "E000X"})
				return
			}

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

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

			relPath := strings.Replace(opFQName, ".", string(filepath.Separator), -1)
			absPath := filepath.Join(cwd, relPath+".yaml")
			_, err = EnsureDirExists(filepath.Dir(absPath))
			if err != nil {
				fail(&Error{Msg: err.Error(), Code: "E000X"})
				return
			}

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

			err = ioutil.WriteFile(absPath, body, os.ModePerm)
			if err != nil {
				fail(&Error{Msg: err.Error(), Code: "E000X"})
				return
			}
			sendSuccess(w, nil)
		}
	}},
	"/meta/visual/": {func(e *api.Environ, w http.ResponseWriter, r *http.Request) {
		fail := func(err *Error) {
			sendFailure(w, &responseBad{err})
		}

		if r.Method == "GET" {
			var err error
			var b []byte
			opFQName := r.FormValue("fqop")

			relPath := strings.Replace(opFQName, ".", string(filepath.Separator), -1)
			absPath, p, err := e.GetFilePathWithFileEnding(relPath, "")
			if err != nil {
				fail(&Error{Msg: err.Error(), Code: "E000X"})
				return
			}

			absPath, _, err = e.GetFilePathWithFileEnding(relPath+SuffixVisual, p)
			b, err = ioutil.ReadFile(absPath)
			if err != nil {
				fail(&Error{Msg: err.Error(), Code: "E000X"})
				return
			}

			resp := &responseOK{}
			if utils.IsJSON(absPath) {
				err = json.Unmarshal(b, &resp.Data)
			} else if utils.IsYAML(absPath) {
				err = yaml.Unmarshal(b, &resp.Data)
				resp.Data = utils.CleanValue(resp.Data)
			}

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

			sendSuccess(w, resp)
		} else if r.Method == "POST" {

			cwd := e.WorkingDir()
			opFQName := r.FormValue("fqop")

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

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

			relPath := strings.Replace(opFQName, ".", string(filepath.Separator), -1)
			absPath := filepath.Join(cwd, relPath+SuffixVisual+".yaml")
			_, err = EnsureDirExists(filepath.Dir(absPath))
			if err != nil {
				fail(&Error{Msg: err.Error(), Code: "E000X"})
				return
			}

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

			err = ioutil.WriteFile(absPath, body, os.ModePerm)
			if err != nil {
				fail(&Error{Msg: err.Error(), Code: "E000X"})
				return
			}
			sendSuccess(w, nil)
		}
	}},
}}
View Source
var RunnerService = &Service{map[string]*Endpoint{
	"/": {func(e *api.Environ, w http.ResponseWriter, r *http.Request) {
		if r.Method == "POST" {
			type runInstructionJSON struct {
				Fqn    string          `json:"fqn"`
				Props  core.Properties `json:"props"`
				Gens   core.Generics   `json:"gens"`
				Stream bool            `json:"stream"`
			}

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

			var data outJSON

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

			port := 50000
			portUsed := true
			for portUsed {
				port++
				portUsed = false
				for _, ri := range runningInstances {
					if ri.port == port {
						portUsed = true
						break
					}
				}
			}

			var httpDef *core.OperatorDef
			if ri.Stream {
				httpDef, err = constructHttpStreamEndpoint(e, port, ri.Fqn, ri.Gens, ri.Props)
			} else {
				httpDef, err = constructHttpEndpoint(e, port, ri.Fqn, ri.Gens, ri.Props)
			}
			if err != nil {
				data = outJSON{Status: "error", Error: &Error{Msg: err.Error(), Code: "E000X"}}
				writeJSON(w, &data)
				return
			}

			packagedOperator := strings.Replace(ri.Fqn+SuffixPacked, ".", string(filepath.Separator), -1) + ".yaml"

			bytes, _ := yaml.Marshal(httpDef)
			ioutil.WriteFile(
				filepath.Join(e.WorkingDir(), packagedOperator),
				bytes,
				os.ModePerm,
			)

			op, err := e.BuildAndCompileOperator(packagedOperator, nil, nil)
			if err != nil {
				data = outJSON{Status: "error", Error: &Error{Msg: err.Error(), Code: "E000X"}}
				writeJSON(w, &data)
				return
			}

			handle := rnd.Int63()
			runningInstances[handle] = struct {
				port int
				op   *core.Operator
			}{port, op}

			op.Start()
			op.Main().In().Push(nil)

			data.Status = "success"
			data.Handle = strconv.FormatInt(handle, 16)
			data.URL = "http://localhost:" + strconv.Itoa(port)

			port++

			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
			}

			handle, _ := strconv.ParseInt(si.Handle, 16, 64)

			if ii, ok := runningInstances[handle]; !ok {
				data = outJSON{Status: "error", Error: &Error{Msg: "Unknown handle", Code: "E000X"}}
				writeJSON(w, &data)
				return
			} else {
				go ii.op.Stop()
				delete(runningInstances, handle)

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

		if r.Method == "GET" {
			opFQName := r.FormValue("fqop")

			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)

			read := make(map[string]bool)
			err := packOperator(e, zipWriter, opFQName, read)
			if err != nil {
				fail(&Error{Msg: err.Error(), Code: "E000X"})
				return
			}

			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\"", opFQName))
			w.Header().Set("Content-Transfer-Encoding", "binary")
			w.Header().Set("Content-Length", fmt.Sprintf("%d", len(buf.Bytes())))
			w.Write(buf.Bytes())
		}
	}},
	"/import": {func(e *api.Environ, 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
					}
				}
			}

			baseDir := e.WorkingDir()
			for _, file := range zipReader.File {
				if file.Name == "manifest.yaml" {
					continue
				}

				fileReader, _ := file.Open()
				buf := new(bytes.Buffer)
				buf.ReadFrom(fileReader)
				fpath := filepath.Join(baseDir, filepath.FromSlash(file.Name))
				os.MkdirAll(filepath.Dir(fpath), os.ModePerm)
				ioutil.WriteFile(fpath, buf.Bytes(), os.ModePerm)
				fileReader.Close()
			}

			writeJSON(w, &struct {
				Success bool `json:"success"`
			}{true})
		}
	}},
}}
View Source
var SlangVersion string

Functions

func EnsureDirExists

func EnsureDirExists(dir string) (string, error)

func EnsureEnvironVar

func EnsureEnvironVar(key string, dfltVal string) string

func IsDirEmpty

func IsDirEmpty(dir string) bool

func IsNewestSlangVersion added in v0.1.5

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

Types

type Endpoint

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

type Error

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

type Server

type Server struct {
	Env  *api.Environ
	Host string
	Port int
	// contains filtered or unexported fields
}

func New

func New(host string, port int) *Server

func (*Server) AddAppServer

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

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) 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

Jump to

Keyboard shortcuts

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