func CreateRouterPaths() {
	helper.SetRouterRoot(true)
	for _, path := range routerzk.ZkPaths {
		Zk.Touch(path)
	}
	helper.SetRouterRoot(false)
	for _, path := range routerzk.ZkPaths {
		Zk.Touch(path)
	}
	for _, zone := range AvailableZones {
		Zk.Touch(helper.GetBaseRouterPath(true, zone))
		Zk.Touch(helper.GetBaseRouterPath(false, zone))
	}
}
Exemple #2
0
func ReserveRouterPortAndUpdateTrie(internal bool, app, sha, env string) (string, bool, error) {
	helper.SetRouterRoot(internal)
	var (
		err      error
		created  = false
		port     = ""
		trieName = ""
	)
	// reserve port for app env
	if !HasRouterPortForAppEnv(internal, app, env) {
		created = true
	}
	if port, err = reserveRouterPort(internal, app, env); err != nil {
		return port, created, err
	}
	if trieName, err = UpdateAppEnvTrie(internal, app, sha, env); err != nil {
		return port, created, err
	}
	// now port is reserved and trie is created so we can actually create port for router
	portUInt, err := strconv.ParseUint(port, 10, 16)
	if err != nil {
		return port, created, err
	}
	err = routerzk.SetPort(Zk.Conn, routercfg.Port{
		Port: uint16(portUInt),
		Trie: trieName,
	})
	if err != nil {
		return port, created, err
	}
	// return true if port was created
	return port, created, err
}
Exemple #3
0
func (e *GetAppEnvPortExecutor) Execute(t *Task) (err error) {
	if e.arg.App == "" {
		return errors.New("Please specify an app")
	} else if e.arg.Env == "" {
		return errors.New("Please specify an environment")
	}
	zkApp, err := datamodel.GetApp(e.arg.App)
	if err != nil {
		return err
	}
	zrp := datamodel.GetRouterPorts(zkApp.Internal)
	fmt.Printf("ROUTER PORTS: %+v\n", zrp)
	portStr := zrp.AppEnvMap[helper.GetAppEnvTrieName(e.arg.App, e.arg.Env)]
	if portStr == "" {
		return errors.New("port not found")
	}

	fmt.Printf("PORT STRING: %+v -> %+v\n", helper.GetAppEnvTrieName(e.arg.App, e.arg.Env), portStr)
	port, err := strconv.ParseUint(portStr, 10, 16)
	if err != nil {
		return err
	}
	helper.SetRouterRoot(zkApp.Internal)
	e.reply.Port, err = routerzk.GetPort(datamodel.Zk.Conn, uint16(port))
	return err
}
func (s *DatamodelSuite) TestReserveRouterPortAndUpdateTrie(c *C) {
	Zk.RecursiveDelete(helper.GetBaseRouterPortsPath(true))
	Zk.RecursiveDelete(helper.GetBaseRouterPortsPath(false))
	Zk.RecursiveDelete(helper.GetBaseLockPath())
	Zk.RecursiveDelete("/atlantis/router")
	CreateRouterPaths()
	CreateRouterPortsPaths()
	CreateLockPaths()

	MinRouterPort = uint16(65533)
	MaxRouterPort = uint16(65535)

	helper.SetRouterRoot(true)
	port, created, err := ReserveRouterPortAndUpdateTrie(true, "app", "sha", "env")
	c.Assert(err, IsNil)
	c.Assert(created, Equals, true)
	c.Assert(port, Equals, "65533")
	trie, err := routerzk.GetTrie(Zk.Conn, helper.GetAppEnvTrieName("app", "env"))
	c.Assert(err, IsNil)
	c.Assert(len(trie.Rules), Equals, 1)
	port, created, err = ReserveRouterPortAndUpdateTrie(true, "app", "sha2", "env")
	c.Assert(err, IsNil)
	c.Assert(created, Equals, false)
	c.Assert(port, Equals, "65533")
	trie, err = routerzk.GetTrie(Zk.Conn, helper.GetAppEnvTrieName("app", "env"))
	c.Assert(err, IsNil)
	c.Assert(len(trie.Rules), Equals, 2)
}
Exemple #5
0
func (e *UpdateRuleExecutor) Execute(t *Task) (err error) {
	if e.arg.Rule.Name == "" {
		return errors.New("Please specify a name")
	} else if e.arg.Rule.Type == "" {
		return errors.New("Please specify a type")
	} else if e.arg.Rule.Value == "" {
		return errors.New("Please specify a value")
	} else if e.arg.Rule.Next == "" && e.arg.Rule.Pool == "" {
		return errors.New("Please specify either a next trie or a pool")
	}
	// fill in current cname suffixes in multi-host rules
	if e.arg.Rule.Type == "multi-host" && dns.Provider != nil {
		suffix, err := dns.Provider.Suffix(Region)
		if err != nil {
			return err
		}
		list := strings.Join(helper.GetAppCNameSuffixes(suffix), ",")
		e.arg.Rule.Value = fmt.Sprintf("%s:%s", e.arg.Rule.Value, list)
	}

	helper.SetRouterRoot(e.arg.Rule.Internal)
	err = routerzk.SetRule(datamodel.Zk.Conn, e.arg.Rule)
	if err != nil {
		e.reply.Status = StatusError
	} else {
		e.reply.Status = StatusOk
	}
	return err
}
Exemple #6
0
func CleanupCreatedPoolRefs(internal bool, app, sha, env string) error {
	helper.SetRouterRoot(internal)
	// remove static rule, cleanup rule from trie if needed
	ruleName := helper.GetAppShaEnvStaticRuleName(app, sha, env)
	trieName := helper.GetAppEnvTrieName(app, env)
	// remove static rule from trie
	trie, err := routerzk.GetTrie(Zk.Conn, trieName)
	if err != nil {
		return err
	}
	newRules := []string{}
	for _, rule := range trie.Rules {
		if rule != ruleName {
			newRules = append(newRules, rule)
		}
	}
	if len(trie.Rules) != len(newRules) {
		trie.Rules = newRules
		err = routerzk.SetTrie(Zk.Conn, trie)
		if err != nil {
			return err
		}
	}
	// delete static rule
	err = routerzk.DelRule(Zk.Conn, ruleName)
	if err != nil {
		return err
	}
	return nil
}
Exemple #7
0
func (e *ListPortsExecutor) Execute(t *Task) (err error) {
	helper.SetRouterRoot(e.arg.Internal)
	e.reply.Ports, err = routerzk.ListPorts(datamodel.Zk.Conn)
	if err == nil {
		sort.Sort(PortSortable(e.reply.Ports))
	}
	return err
}
Exemple #8
0
func (e *GetPortExecutor) Execute(t *Task) (err error) {
	if e.arg.Port == 0 {
		return errors.New("Please specify a port")
	}
	helper.SetRouterRoot(e.arg.Internal)
	e.reply.Port, err = routerzk.GetPort(datamodel.Zk.Conn, e.arg.Port)
	return err
}
Exemple #9
0
func (e *UpdatePortExecutor) Execute(t *Task) (err error) {
	if e.arg.Port.Trie == "" {
		return errors.New("Please specify a trie")
	}
	if e.arg.Port.Port == uint16(0) {
		return errors.New("Please specify a port")
	}
	helper.SetRouterRoot(e.arg.Port.Internal)
	return routerzk.SetPort(datamodel.Zk.Conn, e.arg.Port)
}
Exemple #10
0
func (e *ListTriesExecutor) Execute(t *Task) (err error) {
	helper.SetRouterRoot(e.arg.Internal)
	e.reply.Tries, err = routerzk.ListTries(datamodel.Zk.Conn)
	if err != nil {
		e.reply.Status = StatusError
	} else {
		sort.Strings(e.reply.Tries)
		e.reply.Status = StatusOk
	}
	return err
}
Exemple #11
0
func DeleteFromPool(containers []string) error {
	pools := map[bool]map[string]*poolDefinition{}
	pools[true] = map[string]*poolDefinition{}
	pools[false] = map[string]*poolDefinition{}
	for _, cont := range containers {
		inst, err := GetInstance(cont)
		if err != nil {
			// instance doesn't exist
			continue
		}
		name := helper.CreatePoolName(inst.App, inst.Sha, inst.Env)
		zkApp, err := GetApp(inst.App)
		if err != nil {
			return err
		}
		poolDef := pools[zkApp.Internal][name]
		if poolDef == nil {
			poolDef = &poolDefinition{
				app:   inst.App,
				sha:   inst.Sha,
				env:   inst.Env,
				insts: []*ZkInstance{},
			}
			pools[zkApp.Internal][name] = poolDef
		}
		pools[zkApp.Internal][name].insts = append(poolDef.insts, inst)
	}
	for internal, allPools := range pools {
		helper.SetRouterRoot(internal)
		for name, poolDef := range allPools {
			// remove hosts
			hosts := []string{}
			for _, inst := range poolDef.insts {
				hosts = append(hosts, fmt.Sprintf("%s:%d", inst.Host, inst.Port))
			}
			routerzk.DelHosts(Zk.Conn, name, hosts)
			// delete pool if no hosts exist
			getHosts, err := routerzk.GetHosts(Zk.Conn, name)
			if err != nil || len(getHosts) == 0 {
				err = routerzk.DelPool(Zk.Conn, name)
				if err != nil {
					log.Println("Error trying to clean up pool:", err)
				}
				err = CleanupCreatedPoolRefs(internal, poolDef.app, poolDef.sha, poolDef.env)
				if err != nil {
					log.Println("Error trying to clean up pool:", err)
				}
			}
		}
	}
	return nil
}
Exemple #12
0
func (e *GetTrieExecutor) Execute(t *Task) (err error) {
	if e.arg.Name == "" {
		return errors.New("Please specify a name")
	}
	helper.SetRouterRoot(e.arg.Internal)
	e.reply.Trie, err = routerzk.GetTrie(datamodel.Zk.Conn, e.arg.Name)
	if err != nil {
		e.reply.Status = StatusError
	} else {
		e.reply.Status = StatusOk
	}
	return err
}
Exemple #13
0
func (e *UpdatePoolExecutor) Execute(t *Task) error {
	if e.arg.Pool.Name == "" {
		return errors.New("Please specify a name")
	} else if e.arg.Pool.Config.HealthzEvery == "" {
		return errors.New("Please specify a healthz check frequency")
	} else if e.arg.Pool.Config.HealthzTimeout == "" {
		return errors.New("Please specify a healthz timeout")
	} else if e.arg.Pool.Config.RequestTimeout == "" {
		return errors.New("Please specify a request timeout")
	} // no need to check hosts. an empty pool is still a valid pool
	helper.SetRouterRoot(e.arg.Pool.Internal)
	err := routerzk.SetPool(datamodel.Zk.Conn, e.arg.Pool)
	if err != nil {
		e.reply.Status = StatusError
		return err
	}
	// diff pools and update
	existingHosts, err := routerzk.GetHosts(datamodel.Zk.Conn, e.arg.Pool.Name)
	if err != nil {
		e.reply.Status = StatusError
		return err
	}
	delHosts := []string{}
	for name, _ := range existingHosts {
		if _, ok := e.arg.Pool.Hosts[name]; !ok {
			delHosts = append(delHosts, name)
		}
	}
	newHosts := map[string]routercfg.Host{}
	for name, newHost := range e.arg.Pool.Hosts {
		if _, ok := existingHosts[name]; !ok {
			newHosts[name] = newHost
		}
	}
	err = routerzk.AddHosts(datamodel.Zk.Conn, e.arg.Pool.Name, newHosts)
	if err != nil {
		e.reply.Status = StatusError
		return err
	}
	err = routerzk.DelHosts(datamodel.Zk.Conn, e.arg.Pool.Name, delHosts)
	if err != nil {
		e.reply.Status = StatusError
		return err
	}
	e.reply.Status = StatusOk
	return nil
}
Exemple #14
0
func UpdateAppEnvTrie(internal bool, app, sha, env string) (string, error) {
	helper.SetRouterRoot(internal)
	// create trie (if it doesn't exist)
	trieName := helper.GetAppEnvTrieName(app, env)
	if exists, err := routerzk.TrieExists(Zk.Conn, trieName); !exists || err != nil {
		err = routerzk.SetTrie(Zk.Conn, routercfg.Trie{
			Name:     trieName,
			Rules:    []string{},
			Internal: internal,
		})
		if err != nil {
			return trieName, err
		}
	}
	// if sha != "" attach pool as static rule (if trie is empty)
	if sha != "" {
		// if static rule does not exist, create it
		ruleName := helper.GetAppShaEnvStaticRuleName(app, sha, env)
		poolName := helper.CreatePoolName(app, sha, env)
		if exists, err := routerzk.RuleExists(Zk.Conn, ruleName); !exists || err != nil {
			err = routerzk.SetRule(Zk.Conn, routercfg.Rule{
				Name:     ruleName,
				Type:     "static",
				Value:    "true",
				Pool:     poolName,
				Internal: internal,
			})
			if err != nil {
				return trieName, err
			}
		}
		trie, err := routerzk.GetTrie(Zk.Conn, trieName)
		if err != nil {
			return trieName, err
		}
		if len(trie.Rules) == 0 {
			trie.Rules = []string{ruleName}
		} else {
			trie.Rules = append(trie.Rules, ruleName)
		}
		if err = routerzk.SetTrie(Zk.Conn, trie); err != nil {
			return trieName, err
		}
	}
	return trieName, nil
}
Exemple #15
0
func ReclaimRouterPortsForEnv(internal bool, env string) error {
	helper.SetRouterRoot(internal)
	lock := NewRouterPortsLock(internal)
	lock.Lock()
	defer lock.Unlock()
	zrp := GetRouterPorts(internal)
	ports, err := zrp.reclaimEnv(env)
	if err != nil {
		return err
	}
	for _, port := range ports {
		if err := routerzk.DelPort(Zk.Conn, port); err != nil {
			log.Printf("Error reclaiming port %d for env %s", port, env)
			// don't fail here
			// TODO email appsplat
		}
	}
	return nil
}
Exemple #16
0
func AddToPool(containers []string) error {
	pools := map[bool]map[string][]*ZkInstance{}
	pools[true] = map[string][]*ZkInstance{}
	pools[false] = map[string][]*ZkInstance{}
	for _, cont := range containers {
		inst, err := GetInstance(cont)
		if err != nil {
			// instance doesn't exist
			continue
		}
		name := helper.CreatePoolName(inst.App, inst.Sha, inst.Env)
		zkApp, err := GetApp(inst.App)
		if err != nil {
			return err
		}
		currInsts := pools[zkApp.Internal][name]
		if currInsts == nil {
			currInsts = []*ZkInstance{}
		}
		pools[zkApp.Internal][name] = append(currInsts, inst)
	}
	for internal, allPools := range pools {
		helper.SetRouterRoot(internal)
		for name, insts := range allPools {
			// create pool if we need to
			if exists, err := routerzk.PoolExists(Zk.Conn, name); !exists || err != nil {
				if err = routerzk.SetPool(Zk.Conn, defaultPool(name, internal)); err != nil {
					return err
				}
			}
			// add hosts
			hosts := map[string]routercfg.Host{}
			for _, inst := range insts {
				address := fmt.Sprintf("%s:%d", inst.Host, inst.Port)
				hosts[address] = routercfg.Host{Address: address}
			}
			if err := routerzk.AddHosts(Zk.Conn, name, hosts); err != nil {
				return err
			}
		}
	}
	return nil
}
func (s *DatamodelSuite) TestRouterExternalPool(c *C) {
	Zk.RecursiveDelete("/atlantis/router")
	Zk.RecursiveDelete("/atlantis/apps")
	Zk.RecursiveDelete(helper.GetBaseInstancePath())
	CreateRouterPaths()
	CreateAppPath()
	// fake register app
	CreateOrUpdateApp(false, false, app, "ssh://[email protected]/app", "/", "*****@*****.**")
	CreateOrUpdateApp(false, false, "app2", "ssh://[email protected]/app", "/", "*****@*****.**")
	// do tests
	instance, err := CreateInstance(app, sha, env, host+"-1")
	c.Assert(err, IsNil)
	instance.SetPort(uint16(1337))
	instance2, err := CreateInstance(app, sha, env, host+"-2")
	c.Assert(err, IsNil)
	instance2.SetPort(uint16(1338))
	c.Assert(AddToPool([]string{instance.ID, instance2.ID}), IsNil)
	theName := helper.CreatePoolName(app, sha, env)
	helper.SetRouterRoot(false)
	thePool, err := routerzk.GetPool(Zk.Conn, theName)
	c.Assert(err, IsNil)
	c.Assert(thePool.Name, Equals, theName)
	c.Assert(thePool.Config.HealthzEvery, Not(Equals), "")
	c.Assert(thePool.Config.HealthzTimeout, Not(Equals), "")
	c.Assert(thePool.Config.RequestTimeout, Not(Equals), "")
	c.Assert(thePool.Hosts, DeepEquals, map[string]config.Host{host + "-1:1337": config.Host{Address: host + "-1:1337"}, host + "-2:1338": config.Host{Address: host + "-2:1338"}})
	newInstance, err := CreateInstance("app2", "sha1", "env1", host+"-1")
	c.Assert(err, IsNil)
	newInstance.SetPort(uint16(1339))
	newInstance2, err := CreateInstance(app, sha, env, host+"-3")
	c.Assert(err, IsNil)
	newInstance2.SetPort(uint16(1340))
	c.Assert(DeleteFromPool([]string{instance2.ID}), IsNil)
	instance2.Delete()
	c.Assert(AddToPool([]string{newInstance.ID, newInstance2.ID}), IsNil)
	helper.SetRouterRoot(false)
	thePool, err = routerzk.GetPool(Zk.Conn, theName)
	c.Assert(err, IsNil)
	c.Assert(thePool.Name, Equals, theName)
	c.Assert(thePool.Config.HealthzEvery, Not(Equals), "")
	c.Assert(thePool.Config.HealthzTimeout, Not(Equals), "")
	c.Assert(thePool.Config.RequestTimeout, Not(Equals), "")
	c.Assert(thePool.Hosts, DeepEquals, map[string]config.Host{host + "-1:1337": config.Host{Address: host + "-1:1337"}, host + "-3:1340": config.Host{Address: host + "-3:1340"}})
	helper.SetRouterRoot(false)
	thePool2, err := routerzk.GetPool(Zk.Conn, helper.CreatePoolName("app2", "sha1", "env1"))
	c.Assert(err, IsNil)
	c.Assert(thePool2.Name, Equals, helper.CreatePoolName("app2", "sha1", "env1"))
	c.Assert(thePool2.Config.HealthzEvery, Not(Equals), "")
	c.Assert(thePool2.Config.HealthzTimeout, Not(Equals), "")
	c.Assert(thePool2.Config.RequestTimeout, Not(Equals), "")
	c.Assert(thePool2.Hosts, DeepEquals, map[string]config.Host{host + "-1:1339": config.Host{Address: host + "-1:1339"}})
	helper.SetRouterRoot(false)
	pools, err := routerzk.ListPools(Zk.Conn)
	c.Assert(err, IsNil)
	sort.Strings(pools)
	c.Assert(pools, DeepEquals, []string{thePool2.Name, thePool.Name})
	c.Assert(DeleteFromPool([]string{instance.ID, newInstance.ID, newInstance2.ID}), IsNil)
	instance.Delete()
	newInstance.Delete()
	newInstance2.Delete()
	helper.SetRouterRoot(false)
	thePool, err = routerzk.GetPool(Zk.Conn, theName)
	c.Assert(err, Not(IsNil))
}