func (bs *BalancingService) SubscribeEvents() { tree_event.ON(tree_event.ON_DOCKER_INIT, func(e *tree_event.Event) { var err tree_lib.TreeError err.From = tree_lib.FROM_SUBSCRIBE_EVENTS if e.LocalVar == nil { tree_log.Info(err.From, "Containers list is nil during INIT event") return } for _, c := range e.LocalVar.([]docker.APIContainers) { if port, ok := bs.DockerImages[c.Image]; ok { var ci *docker.Container ci, err.Err = tree_docker.DockerClient.InspectContainer(c.ID) if !err.IsNull() { continue } cont_addr := Address{IP: ci.NetworkSettings.IPAddress, Port: port} err.Err = bs.AddDestination(cont_addr) if !err.IsNull() { return } containerAddressMap[c.ID] = cont_addr } } }) tree_event.ON(tree_event.ON_DOCKER_CONTAINER_START, func(e *tree_event.Event) { var err tree_lib.TreeError if e.LocalVar == nil { tree_log.Info(log_from_balancer, "Container Info is nil during container Start event") return } ci := e.LocalVar.(*tree_docker.ContainerInfo) if port, ok := bs.DockerImages[ci.Image]; ok { cont_addr := Address{IP: ci.InspectContainer.NetworkSettings.IPAddress, Port: port} err.Err = bs.AddDestination(cont_addr) if !err.IsNull() { return } containerAddressMap[ci.ID] = cont_addr } }) tree_event.ON(tree_event.ON_DOCKER_CONTAINER_STOP, func(e *tree_event.Event) { if e.LocalVar == nil { tree_log.Info(log_from_balancer, "Container ID is nil during container Stop event") return } cont_id := e.LocalVar.(string) if cont_addr, ok := containerAddressMap[cont_id]; ok { bs.DeleteDestination(cont_addr) delete(containerAddressMap, cont_id) bs.CheckForStopEvent() } }) }
func HandleAddCustomEventHandlers(e *tree_event.Event, api_cmd Command) { var ( out = &WriterCallback{BufferMaxSize: 1024} handler_data map[string]interface{} err tree_lib.TreeError ev_data []byte ) err.From = tree_lib.FROM_ADD_CUSTOM_EVENT err.Err = ffjson.Unmarshal(api_cmd.Data, &handler_data) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } out.OutCallback = func(data []byte, ended bool) { cb_cmd := api_cmd cb_cmd.Ended = ended cb_cmd.Data = data ev_data, err.Err = ffjson.Marshal(cb_cmd) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } SendCommandCallback(e, ev_data) } defer out.End() event_name := handler_data["name"].(string) handles_interfaces := handler_data["handlers"].([]interface{}) var ( handles_interfaces_data []byte handlers []custom_event.Handler ) handles_interfaces_data, err.Err = ffjson.Marshal(handles_interfaces) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } err.Err = ffjson.Unmarshal(handles_interfaces_data, &handlers) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } err = custom_event.ON(event_name, handlers...) if !err.IsNull() { tree_log.Error(err.From, err.Error()) } }
func HandleContainerCommand(ev *tree_event.Event, cmd Command) { var ( out = &WriterCallback{BufferMaxSize: 1024} docker_cmd = tree_docker.DockerCmd{} err tree_lib.TreeError ev_data []byte ) err.From = tree_lib.FROM_HANDLE_CONTAINER_COMMAND err.Err = ffjson.Unmarshal(cmd.Data, &docker_cmd) if !err.IsNull() { tree_log.Error(err.From, "unable to unmarshal command data as a docker command -> ", err.Error()) return } out.OutCallback = func(data []byte, ended bool) { cb_cmd := cmd cb_cmd.Ended = ended cb_cmd.Data = data ev_data, err.Err = ffjson.Marshal(cb_cmd) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } SendCommandCallback(ev, ev_data) } defer out.End() tree_docker.ContainerCommands(&docker_cmd, out) }
// Executing some commands using exec.Command functionality from Go in OS func HandleExecCommand(e *tree_event.Event, api_cmd Command) { var ( out = &WriterCallback{BufferMaxSize: 1024} cmd_str = string(api_cmd.Data) cmd_options = strings.Split(cmd_str, " ") cmd = exec.Command(cmd_options[0], cmd_options[1:]...) err tree_lib.TreeError ev_data []byte ) err.From = tree_lib.FROM_HANDLE_EXEC_COMMAND out.OutCallback = func(data []byte, ended bool) { cb_cmd := api_cmd cb_cmd.Ended = ended cb_cmd.Data = data ev_data, err.Err = ffjson.Marshal(cb_cmd) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } SendCommandCallback(e, ev_data) } defer out.End() cmd.Stdout = out cmd.Stderr = out err.Err = cmd.Run() if !err.IsNull() { tree_log.Error(err.From, err.Error()) } }
func HandleNodeCommand(cmd *cobra.Command, args []string) { var ( name string err tree_lib.TreeError ) err.From = tree_lib.FROM_HANDLE_NODE_COMMAND name, err.Err = cmd.Flags().GetString("set-name") if !err.IsNull() { tree_log.Error(err.From, err.Error()) } // If we have set-name flag then we just setting current_node in database and exiting if len(name) > 0 { tree_db.Set(tree_db.DB_RANDOM, []byte("current_node"), []byte(name)) return } daemon := false daemon, err.Err = cmd.Flags().GetBool("daemon") if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } if daemon { cmd := exec.Command("/bin/sh", "-c", fmt.Sprintf("%s node > %s 2>&1 &", os.Args[0], tree_log.LogFile)) err.Err = cmd.Run() if !err.IsNull() { log.Fatal(err.Err) } return } name, err.Err = cmd.Flags().GetString("name") if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } if len(name) == 0 { current_node_byte, err := tree_db.Get(tree_db.DB_RANDOM, []byte("current_node")) if !err.IsNull() { tree_log.Error(err.From, "Getting current node name from Random database, ", err.Error()) return } if len(current_node_byte) == 0 { fmt.Println("Name is important for the first time run") return } } else { err = tree_node.SetCurrentNode(name) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } } tree_node.Start() }
func HandleUpdateCommand(ev *tree_event.Event, cmd Command) { var ( data Command info node_info.NodeInfo err tree_lib.TreeError ) err.From = tree_lib.FROM_HANDLE_UPDATE_COMMAND err.Err = ffjson.Unmarshal(ev.Data, &data) if !err.IsNull() { tree_log.Error(err.From, err.Error()) } err.Err = ffjson.Unmarshal(data.Data, &info) if !err.IsNull() { tree_log.Error(err.From, err.Error()) } UpdateNodeChange(info) SendCommandCallback(ev, ev.Data) }
func TriggerFromData(data []byte) { var ( e = new(Event) err tree_lib.TreeError ) err.From = tree_lib.FROM_TRIGGER_FROM_DATA err.Err = ffjson.Unmarshal(data, e) if !err.IsNull() { tree_log.Error(log_from_event, err.Error()) return } Trigger(e) }
func HandleApiCommand(cmd_data []byte, api_out io.Writer) { var ( err tree_lib.TreeError cmd DockerCmd ) err.From = tree_lib.FROM_HANDLE_API_COMMAND err.Err = ffjson.Unmarshal(cmd_data, &cmd) if !err.IsNull() { writeOutput(api_out, true, fmt.Sprintf("--- Unable to parse Container command data: %s", string(cmd_data)), map[string]string{}) return } ContainerCommands(&cmd, api_out) fmt.Println(string(cmd_data)) }
func ContainerCommands(cmd *DockerCmd, out io.Writer) { var ( err tree_lib.TreeError ) err.From = tree_lib.FROM_CONTAINER_COMMANDS switch cmd.Command { case COMMAND_DOCKER_CONTAINER_CREATE, COMMAND_DOCKER_CONTAINER_START: { var ( cont *docker.Container conf = &docker.Config{} host_conf = &docker.HostConfig{} cont_count int start_cont = false ) if cc, ok := cmd.Content["count"]; ok { cont_count, err.Err = strconv.Atoi(cc) if !err.IsNull() { writeOutput(out, true, fmt.Sprintf("--- Invalid number given for Containers count: %s", cc), cmd.Content) return } } else { cont_count = 1 } if run_cmd, ok := cmd.Content["cmd"]; ok { conf.Cmd = []string{run_cmd} } if img, ok := cmd.Content["image"]; ok { conf.Image = img } // By default we just don't need any output conf.AttachStderr = false conf.AttachStdin = false conf.AttachStdout = false if cs, ok := cmd.Content["cpu"]; ok { var cs_int int cs_int, err.Err = strconv.Atoi(cs) if !err.IsNull() { writeOutput(out, true, fmt.Sprintf("--- Invalid number given for CPU Shares: %s", cs), cmd.Content) return } host_conf.CPUShares = int64(cs_int) } if ram, ok := cmd.Content["ram"]; ok { var ram_int int ram_int, err.Err = strconv.Atoi(ram) if !err.IsNull() { writeOutput(out, true, fmt.Sprintf("--- Invalid number given for RAM: %s", ram), cmd.Content) return } host_conf.Memory = int64(ram_int) } if st, ok := cmd.Content["start"]; ok { switch st { case "yes", "y", "true", "t": start_cont = true case "no", "n", "false", "f": start_cont = false } } // If we just want to start container by ID just running it and returning if cmd.Command == COMMAND_DOCKER_CONTAINER_START { if cid, ok := cmd.Content["container"]; ok { err.Err = DockerClient.StartContainer(cid, host_conf) if !err.IsNull() { writeOutput(out, true, fmt.Sprintf("--- Unable to start container: %s", err.Error()), cmd.Content) return } writeOutput(out, false, fmt.Sprintf("Container Started \n Container -> %s\n", cid), cmd.Content) } return } for i := 0; i < cont_count; i++ { cont, err.Err = DockerClient.CreateContainer(docker.CreateContainerOptions{ Config: conf, HostConfig: host_conf, }) if !err.IsNull() { writeOutput(out, true, fmt.Sprintf("--- Container creation error: %s", err.Error()), cmd.Content) return } writeOutput(out, false, fmt.Sprintf("Container Created \n ID -> %s\n Name -> %s\n", cont.ID, cont.Name), cmd.Content) if start_cont { err.Err = DockerClient.StartContainer(cont.ID, host_conf) if !err.IsNull() { writeOutput(out, true, fmt.Sprintf("--- Unable to start container: %s", err.Error()), cmd.Content) return } writeOutput(out, false, fmt.Sprintf("Container Started \n Name -> %s\n", cont.Name), cmd.Content) } } } case COMMAND_DOCKER_CONTAINER_PAUSE: { if cid, ok := cmd.Content["container"]; ok { err.Err = DockerClient.PauseContainer(cid) if !err.IsNull() { writeOutput(out, true, fmt.Sprintf("--- Unable to pause container: %s", err.Error()), cmd.Content) return } writeOutput(out, false, fmt.Sprintf("Container Paused \n Container -> %s\n", cid), cmd.Content) } } case COMMAND_DOCKER_CONTAINER_RESUME: { if cid, ok := cmd.Content["container"]; ok { err.Err = DockerClient.UnpauseContainer(cid) if !err.IsNull() { writeOutput(out, true, fmt.Sprintf("--- Unable to Resume container: %s", err.Error()), cmd.Content) return } writeOutput(out, false, fmt.Sprintf("Container Resumed \n Container -> %s\n", cid), cmd.Content) } } case COMMAND_DOCKER_CONTAINER_DELETE: { if cid, ok := cmd.Content["container"]; ok { DockerClient.StopContainer(cid, 0) // Stopping container if it exists err.Err = DockerClient.RemoveContainer(docker.RemoveContainerOptions{ID: cid, Force: true}) if !err.IsNull() { writeOutput(out, true, fmt.Sprintf("--- Unable to Resume container: %s", err.Error()), cmd.Content) return } writeOutput(out, false, fmt.Sprintf("Container Resumed \n Container -> %s\n", cid), cmd.Content) } } case COMMAND_DOCKER_CONTAINER_STOP: { var ( stop_timeout = uint(0) st_int int ) if tm, ok := cmd.Content["timeout"]; ok { st_int, err.Err = strconv.Atoi(tm) if !err.IsNull() { writeOutput(out, true, fmt.Sprintf("--- Invalid number given for Timeout: %s", tm), cmd.Content) return } stop_timeout = uint(st_int) } if cid, ok := cmd.Content["container"]; ok { err.Err = DockerClient.StopContainer(cid, stop_timeout) if !err.IsNull() { writeOutput(out, true, fmt.Sprintf("--- Unable to Stop container: %s", err.Error()), cmd.Content) return } writeOutput(out, false, fmt.Sprintf("Container Stopped \n Container -> %s\n", cid), cmd.Content) } } case COMMAND_DOCKER_IMAGE_PULL: { var ( registry string repository string tag string image string img_repo string registery_username string registery_email string registery_passord string registery_address string ) if r, ok := cmd.Content["registry"]; ok { registry = r } else { registry = "" } if im, ok := cmd.Content["image"]; ok { image = im } else { writeOutput(out, true, "--- Image Name is required during image pull process", cmd.Content) return } str_split := strings.Split(image, ":") if len(str_split) != 2 { writeOutput(out, true, "--- Please Specify image tag name with this format <repository>:<tag>", cmd.Content) return } repository = str_split[0] tag = str_split[1] if len(registry) > 0 { img_repo = fmt.Sprintf("%s/%s", registry, repository) } else { img_repo = repository } // Getting Registery authentication data if ru, ok := cmd.Content["registry_username"]; ok { registery_username = ru } if rp, ok := cmd.Content["registry_password"]; ok { registery_passord = rp } if rem, ok := cmd.Content["registry_email"]; ok { registery_email = rem } if raddr, ok := cmd.Content["registry_address"]; ok { registery_address = raddr } err.Err = DockerClient.PullImage(docker.PullImageOptions{ Registry: registry, Repository: img_repo, Tag: tag, OutputStream: nil, }, docker.AuthConfiguration{ Username: registery_username, Email: registery_email, Password: registery_passord, ServerAddress: registery_address, }) if !err.IsNull() { writeOutput(out, true, fmt.Sprintf("--- Pulling image error: %s", err.Error()), cmd.Content) return } err.Err = DockerClient.TagImage(fmt.Sprintf("%s:%s", img_repo, tag), docker.TagImageOptions{ Repo: repository, Tag: tag, Force: true, }) if !err.IsNull() { writeOutput(out, true, fmt.Sprintf("--- Error Renaming pulled image %s : %s", fmt.Sprintf("%s:%s", img_repo, tag), err.Error()), cmd.Content) DockerClient.RemoveImageExtended(fmt.Sprintf("%s:%s", img_repo, tag), docker.RemoveImageOptions{Force: true}) return } DockerClient.RemoveImage(fmt.Sprintf("%s:%s", img_repo, tag)) writeOutput(out, false, fmt.Sprintf("Image Created %s", image), cmd.Content) } case COMMAND_DOCKER_IMAGE_DELETE: { var ( image string force = false ) if im, ok := cmd.Content["image"]; ok { image = im } else { writeOutput(out, true, "--- For Deleting image you need to specifi image name", cmd.Content) return } if f, ok := cmd.Content["force"]; ok { switch f { case "yes", "y", "true", "t": force = true case "no", "n", "false", "f": force = false } } err.Err = DockerClient.RemoveImageExtended(image, docker.RemoveImageOptions{Force: force}) if !err.IsNull() { writeOutput(out, true, fmt.Sprintf("--- Error Deleting image %s : %s", image, err.Error()), cmd.Content) return } writeOutput(out, false, fmt.Sprintf("Image deleted %s", image), cmd.Content) } case COMMAND_DOCKER_CONTAINER_INSPECT: { var ( cont_id string container = make(map[string]interface{}) ) if cid, ok := cmd.Content["container"]; ok { cont_id = cid } else { writeOutput(out, true, "--- Container Name or ID is required during inspecting", cmd.Content) return } container[cont_id], err.Err = DockerClient.InspectContainer(cont_id) writeDcOutput(out, DockerCmdOutput{ Error: false, Message: "Container Inspected Successfully", Data: cmd.Content, DataList: container, }) } case COMMAND_DOCKER_CONTAINER_LIST: { var ( all = false containers []docker.APIContainers w_list = make(map[string]interface{}) ) if a, ok := cmd.Content["all"]; ok { switch a { case "yes", "y", "true", "t": all = true case "no", "n", "false", "f": all = false } } containers, err.Err = DockerClient.ListContainers(docker.ListContainersOptions{All: all}) if !err.IsNull() { writeOutput(out, true, "--- Error Getting Container list", cmd.Content) return } for _, c := range containers { w_list[c.ID], err.Err = DockerClient.InspectContainer(c.ID) if !err.IsNull() { writeDcOutput(out, DockerCmdOutput{ Error: true, Message: fmt.Sprintf("--- Error Inspecting container %s", c.ID), Data: cmd.Content, DataList: w_list, }) } } writeDcOutput(out, DockerCmdOutput{ Error: false, Message: "Containers list fetched successfully", Data: cmd.Content, DataList: w_list, }) } case COMMAND_DOCKER_IMAGE_LIST: { var ( all = false images []docker.APIImages w_list = make(map[string]interface{}) ) if a, ok := cmd.Content["all"]; ok { switch a { case "yes", "y", "true", "t": all = true case "no", "n", "false", "f": all = false } } images, err.Err = DockerClient.ListImages(docker.ListImagesOptions{All: all}) if !err.IsNull() { writeOutput(out, true, "--- Error Getting Image list", cmd.Content) return } for _, im := range images { w_list[im.ID], err.Err = DockerClient.InspectImage(im.ID) if !err.IsNull() { writeDcOutput(out, DockerCmdOutput{ Error: true, Message: fmt.Sprintf("--- Error Inspecting image %s", im.ID), Data: cmd.Content, DataList: w_list, }) } } writeDcOutput(out, DockerCmdOutput{ Error: false, Message: "Images list fetched successfully", Data: cmd.Content, DataList: w_list, }) } } }
func CompileConfig(cmd *cobra.Command, args []string) { var ( files []string conf_type string out_file string paths []string files_in_path []string err tree_lib.TreeError ) err.From = tree_lib.FROM_COMPILE_CONFIG files, err.Err = cmd.Flags().GetStringSlice("files") if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } conf_type, err.Err = cmd.Flags().GetString("type") if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } out_file, err.Err = cmd.Flags().GetString("out") if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } if _, err.Err = os.Stat(out_file); err.Err == nil { err.Err = os.Remove(out_file) if !err.IsNull() { tree_log.Error(err.From, err.Error()) } } paths, err.Err = cmd.Flags().GetStringSlice("path") if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } if len(paths) > 0 { files_in_path, err = PathFiles(conf_type, paths) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } for _, a := range files_in_path { files = append(files, a) } } if len(files) > 0 { err = ParseFiles(conf_type, files...) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } } DBFromConfig() err = tree_db.DumpDBPath(out_file) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } // Deleting database dir from console part err.Err = os.RemoveAll(tree_db.DB_DIR) if !err.IsNull() { tree_log.Error(err.From, err.Error()) } }
func handle_api_or_parent_connection(conn *net.TCPConn) { defer conn.Close() // Connection should be closed, after return this function var ( err tree_lib.TreeError msg_data []byte info_data []byte conn_name string is_api = false conn_node_info node_info.NodeInfo api_val *big.Int ) err.From = tree_lib.FROM_HANDLE_API_OR_PARENT_CONNECTION // Making basic handshake to check the API validation // Connected Parent receiving name of the child(current node) and checking is it valid or not // if it is valid name then parent sending his name as an answer // otherwise it sending CLOSE_CONNECTION_MARK and closing connection info_data, err.Err = ffjson.Marshal(node_info.CurrentNodeInfo) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } _, err.Err = tree_lib.SendMessage(info_data, conn) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } info_data, err = tree_lib.ReadMessage(conn) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } conn_name = string(info_data) if conn_name == CLOSE_CONNECTION_MARK { tree_log.Info(err.From, "Connection closed by parent node. Bad tree network handshake ! ", "Parent Addr: ", conn.RemoteAddr().String()) return } err.Err = ffjson.Unmarshal(info_data, &conn_node_info) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } if strings.Contains(conn_node_info.Name, tree_api.API_NAME_PREFIX) { api_val = big.NewInt(conn_node_info.Value) api_connections[api_val] = conn is_api = true } else { // TODO: Think about conn_node_info if we need to more checking for parent node info parentConnection = conn } if is_api { tree_event.TriggerWithData(tree_event.ON_API_CONNECTED, info_data) } else { tree_event.TriggerWithData(tree_event.ON_PARENT_CONNECTED, info_data) } // Listening parent messages for { msg_data, err = tree_lib.ReadMessage(conn) if !err.IsNull() { tree_log.Error(err.From, " reading data from -> ", conn_name, " ", err.Error()) break } // Handling message events handle_message(is_api, true, msg_data) } if is_api { api_connections[api_val] = nil delete(api_connections, api_val) tree_event.TriggerWithData(tree_event.ON_API_DISCONNECTED, info_data) } else { parentConnection = nil tree_event.TriggerWithData(tree_event.ON_PARENT_DISCONNECTED, info_data) } }
func HandleListCommand(ev *tree_event.Event, cmd Command) { var ( info = make(map[string]node_info.NodeInfo) data []byte ev_data Command nodes []string nodes_in_group []string nodes_in_tag []string err tree_lib.TreeError infos Info ) err.From = tree_lib.FROM_HANDLE_LIST_COMMAND err.Err = ffjson.Unmarshal(ev.Data, &ev_data) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } err.Err = ffjson.Unmarshal(ev_data.Data, &infos) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } nodes = infos.Target for _, g := range infos.Group { nodes_in_group, err = tree_db.GetGroupNodes(g) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } for _, n := range nodes_in_group { nodes = append(nodes, n) } } for _, t := range infos.Tag { nodes_in_tag, err = tree_db.GetNodesByTagName(t) if !err.IsNull() { tree_log.Error(err.From, "getting Tags", err.Error()) return } for _, n := range nodes_in_tag { nodes = append(nodes, n) } } for _, n := range nodes { info[n], err = tree_db.GetNodeInfo(n) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } } cb_cmd := cmd cb_cmd.Data, err.Err = ffjson.Marshal(info) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } data, err.Err = ffjson.Marshal(cb_cmd) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } SendCommandCallback(ev, data) }
func init() { var err tree_lib.TreeError err.From = tree_lib.FROM_INIT tree_db, err.Err = bolt.Open(DB_DIR, 0600, nil) if !err.IsNull() { tree_log.Error(log_from_db, " unable to open database", err.Error()) tree_db = nil os.Exit(1) // Without database we can't keep and share configurations, so program should be exited } // creating Buckets in database tree_db.Update(func(tx *bolt.Tx) (err error) { // Setting databases for _, d := range [][]byte{DB_NODE, DB_BALANCER, DB_RANDOM, DB_GROUP, DB_TAG, DB_RELATIONS, DB_REGISTRY, DB_EVENT} { _, err = tx.CreateBucketIfNotExists(d) if err != nil { return err } } return nil }) // Handling node change event tree_event.ON(tree_event.ON_UPDATE_NODE_INFO, func(e *tree_event.Event) { var ( info node_info.NodeInfo ev_info node_info.NodeInfo names []string data []byte mark bool ) err.Err = ffjson.Unmarshal(e.Data, &ev_info) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } info, err = GetNodeInfo(ev_info.Name) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } if len(info.Name) > 0 { err = DeleteNodeFromHisGroups(info.Name) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } err = DeleteNodeFromHisTags(info.Name) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } if len(ev_info.TreeIp) > 0 { info.TreeIp = ev_info.TreeIp mark = true } if ev_info.TreePort != -1 { info.TreePort = ev_info.TreePort mark = true } if len(ev_info.Childs[0]) > 0 { info.Childs = append(info.Childs, ev_info.Childs[0]) } if len(ev_info.Childs[1]) > 0 { if g, ok := tree_lib.ArrayContains(info.Childs, ev_info.Childs[1]); ok { info.Childs = info.Childs[:g+copy(info.Childs[g:], info.Childs[g+1:])] } } if len(ev_info.Groups[0]) > 0 { info.Groups = append(info.Groups, ev_info.Groups[0]) } if len(ev_info.Groups[1]) > 0 { if g, ok := tree_lib.ArrayContains(info.Groups, ev_info.Groups[1]); ok { info.Groups = info.Groups[:g+copy(info.Groups[g:], info.Groups[g+1:])] } } if len(ev_info.Tags[0]) > 0 { info.Tags = append(info.Tags, ev_info.Tags[0]) } if len(ev_info.Tags[1]) > 0 { if g, ok := tree_lib.ArrayContains(info.Tags, ev_info.Tags[1]); ok { info.Tags = info.Tags[:g+copy(info.Tags[g:], info.Tags[g+1:])] } } data, err.Err = ffjson.Marshal(info) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } err = Set(DB_NODE, []byte(ev_info.Name), data) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } names, err = ListNodeNames() if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } err = AddNodeToHisGroups(info.Name) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } err = AddNodeToHisTags(info.Name) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } for _, n := range names { err = SetRelations(n) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } } if node_info.CurrentNodeInfo.Name == ev_info.Name && mark { var e1 tree_event.Event e1.Name = tree_event.ON_RESTART_NODE tree_event.Trigger(&e1) } } else { err = Set(DB_NODE, []byte(ev_info.Name), e.Data) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } names, err = ListNodeNames() if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } err = AddNodeToHisGroups(ev_info.Name) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } err = AddNodeToHisTags(ev_info.Name) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } for _, n := range names { err = SetRelations(n) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } } if node_info.CurrentNodeInfo.Name == ev_info.Name { var e1 *tree_event.Event e1.Name = tree_event.ON_RESTART_NODE tree_event.Trigger(e1) } } }) // Closing database before program will be exited // Just in case if program exiting force or we don't want to make dead lock tree_event.ON(tree_event.ON_PROGRAM_EXIT, func(e *tree_event.Event) { CloseDB() }) }
func init() { // This event will be triggered from Node, when API client will send some command to implement tree_event.ON(tree_event.ON_API_COMMAND, func(ev *tree_event.Event) { var err tree_lib.TreeError err.From = tree_lib.FROM_INIT cmd := Command{} err.Err = ffjson.Unmarshal(ev.Data, &cmd) if !err.IsNull() { tree_log.Error(err.From, "unable to unmarshal event data as a command -> ", err.Error()) return } switch cmd.CommandType { case COMMAND_EXEC: { HandleExecCommand(ev, cmd) } case COMMAND_LIST: { HandleListCommand(ev, cmd) } case COMMAND_UPDATE: { HandleUpdateCommand(ev, cmd) } case COMMAND_CONTAINER: { HandleContainerCommand(ev, cmd) } case COMMAND_ADD_CUSTOM_EVENT: { HandleAddCustomEventHandlers(ev, cmd) } case COMMAND_TRIGGER_EVENT: { HandleTriggerCustomEvent(ev, cmd) } } }) // This event will be triggered from API client when Node will give callback for specific commands tree_event.ON(tree_event.ON_API_COMMAND_CALLBACK, func(ev *tree_event.Event) { var err tree_lib.TreeError err.From = tree_lib.FROM_INIT cmd := Command{} err.Err = ffjson.Unmarshal(ev.Data, &cmd) if !err.IsNull() { tree_log.Error(err.From, "unable to unmarshal event data as a command -> ", err.Error()) return } if cb, ok := subscribed_command_callbacks[cmd.ID]; ok && cb.f != nil { if !cb.f(ev, cmd) { // TODO: Maybe we need mutex to lock deleting process delete(subscribed_command_callbacks, cmd.ID) if cb.c != nil { cb.c <- true // Ending wait chanel in send command } } } }) }
func ListInfos(cmd *cobra.Command, args []string) { var ( err tree_lib.TreeError node string targets []string groups []string tags []string info tree_api.Info ) err.From = tree_lib.FROM_LIST_INFOS node, err.Err = cmd.Flags().GetString("node") if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } targets, err.Err = cmd.Flags().GetStringSlice("target") if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } groups, err.Err = cmd.Flags().GetStringSlice("group") if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } tags, err.Err = cmd.Flags().GetStringSlice("tag") if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } if !tree_api.API_INIT(node) { fmt.Println("Unable to init api client") fmt.Println("Exiting ...") return } var ( api_cmd = tree_api.Command{} wait = make(chan bool) ) info.Group = groups info.Target = targets info.Tag = tags api_cmd.Data, err.Err = ffjson.Marshal(info) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return } api_cmd.ID = tree_lib.RandomString(20) api_cmd.CommandType = tree_api.COMMAND_LIST tree_event.ON(tree_event.ON_CHILD_CONNECTED, func(ev *tree_event.Event) { path := &tree_graph.Path{From: node, Nodes: []string{node}} tree_api.SendCommand(&api_cmd, path, func(e *tree_event.Event, c tree_api.Command) bool { var ( err tree_lib.TreeError info = make(map[string]node_info.NodeInfo) ) err.Err = ffjson.Unmarshal(c.Data, &info) if !err.IsNull() { tree_log.Error(err.From, err.Error()) return false } for _, a := range info { fmt.Println("name: ", a.Name, ", Adress: ", a.TreeIp, ":", a.TreePort, ", Value: ", a.Value) fmt.Println("groups:", a.Groups) fmt.Println("tags:", a.Tags) fmt.Println("childs", a.Childs) } return false }) wait <- true }) <-wait }