Beispiel #1
0
func (helper *Marathon) createService(config *framework.ServiceConfig, instances int) (*framework.ServiceInformation, error) {
	config.DockerCfg = helper.dockerCfg
	copyGlobalHealthCheckToServiceCfg(helper.healthCheckConf, config)
	app := translateServiceConfig(config, instances)
	appResult, err := helper.client.CreateApplication(app)
	if err != nil {
		return nil, err
	} else {

		logger.Instance().Debugln("#### appResult marshall ####")
		jsonresult, _ := json.Marshal(appResult)
		logger.Instance().Debugf("App jsonresult:  \n\n %s", string(jsonresult))

		deployErr := helper.client.WaitOnApplication(app.ID, time.Duration(helper.deployTimeout)*time.Second)

		if deployErr != nil {
			logger.Instance().Errorf("Failed to Create the application: %s, error: %s \n", app.ID, deployErr)
			logger.Instance().Infof("Executing Rollback: Deleting App with ID %s", app.ID)
			helper.DeleteService(app.ID)
			return nil, deployErr
		}

		app, err := helper.client.Application(app.ID)
		if err != nil {
			return nil, err
		} else {
			return helper.getServiceInformationFromApp(app), nil
		}
	}
}
// Register permite registrar a una implementación de Framework, de esta
// manera estara disponible mediante su ID para poder ser instanciado
func Register(name string, factory FrameworkFactory) {
	if factory == nil {
		logger.Instance().Fatal("Se debe pasar como argumento un SchedulerFactory")
	}
	_, registered := frameworkFactories[name]
	if registered {
		logger.Instance().Fatalf("SchedulerFactory %s ya está registrado", name)
	}

	frameworkFactories[name] = factory
}
Beispiel #3
0
func bindPort(publish []string) map[docker.Port][]docker.PortBinding {
	portBindings := map[docker.Port][]docker.PortBinding{}

	for _, v := range publish {
		logger.Instance().Debugln("Procesando el bindeo del puerto", v)
		var dp docker.Port
		reflect.ValueOf(&dp).Elem().SetString(v)
		portBindings[dp] = []docker.PortBinding{{}}
	}

	logger.Instance().Debugf("PortBindings %#v", portBindings)

	return portBindings
}
Beispiel #4
0
// New instancia un nuevo cliente de Swarm
func New(params parameters) (*Framework, error) {
	swarm := &Framework{
		authConfigs: make(map[string]docker.AuthConfiguration),
	}

	var err error
	logger.Instance().Debugf("Configurando Swarm con los parametros %+v", params)
	if params.tlsverify {
		swarm.client, err = docker.NewTLSClient(params.address, params.tlscert, params.tlskey, params.tlscacert)
	} else {
		swarm.client, err = docker.NewClient(params.address)
	}
	if err != nil {
		return nil, err
	}

	registriesURL := []string{"https://registry.it.lan.com", "https://registry.dev.lan.com"}
	for _, v := range registriesURL {
		auth, err := authConfig(params.authfile, v)
		if err != nil {
			return nil, err
		}
		swarm.authConfigs[v] = auth
	}

	return swarm, nil
}
Beispiel #5
0
func (helper *Marathon) DeleteService(id string) error {
	_, err := helper.client.DeleteApplication(id)
	if err != nil {
		logger.Instance().Errorf("Failed to Delete the application: %s, error: %s", id, err)
	}
	return err
}
Beispiel #6
0
func (s *Framework) pullImage(imageName string) error {
	logger.Instance().Infoln("Realizando el pulling de la imagen", imageName)
	var buf bytes.Buffer
	pullImageOpts := docker.PullImageOptions{Repository: imageName, OutputStream: &buf}
	err := s.client.PullImage(pullImageOpts, s.authConfigs["https://registry.it.lan.com"])
	if err != nil {
		return err
	}

	logger.Instance().Debugln(buf.String())

	if invalidOut := regexp.MustCompile("Pulling .+ Error"); invalidOut.MatchString(buf.String()) {
		return errors.New("Problema al descargar la imagen")
	}

	return nil
}
Beispiel #7
0
func (s *Framework) FindServiceInformation(filter framework.ServiceInformationCriteria) ([]*framework.ServiceInformation, error) {
	logger.Instance().Debugln("Obteniendo el listado de contenedores")

	containers, err := s.client.ListContainers(docker.ListContainersOptions{All: true})
	if err != nil {
		return nil, err
	}

	var services []*framework.ServiceInformation
	for _, container := range containers {
		logger.Instance().Debugf("Filtrando el contenedor %+v", container)

		imageName, imageTag := imageAndTag(container.Image)
		sid := imageName + ":" + imageTag

		srv := getService(sid, services)
		if srv == nil {
			srv = &framework.ServiceInformation{
				ID:        sid,
				ImageName: imageName,
				ImageTag:  imageTag,
			}
			services = append(services, srv)
		}

		host, containerName := hostAndContainerName(container.Names[0])
		c := &framework.Instance{
			ID:            container.ID,
			Status:        getStatus(container.Status),
			Host:          host,
			ContainerName: containerName,
			Ports:         mapPorts(container.Ports),
		}
		logger.Instance().Debugf("Mapeando contenedor a %+v", c)
		srv.Instances = append(srv.Instances, c)
	}

	if filter == nil {
		return services, nil
	}

	filtered := filter.MeetCriteria(services)

	return filtered, nil
}
Beispiel #8
0
// NewFromParameters construye un Scheduler a partir de un mapeo de parámetros
// Al menos se debe pasar como parametro address, ya que si no existe se retornara un error
// Si se pasa tlsverify como true los parametros tlscacert, tlscert y tlskey también deben existir
func NewFromParameters(params map[string]interface{}) (*Framework, error) {

	address, ok := params["address"]
	if !ok || fmt.Sprint(address) == "" {
		return nil, errors.New("Parametro address no existe")
	}

	authfile := dockerCfgPath()
	if af, ok := params["authfile"]; !ok || fmt.Sprint(af) == "" {
		logger.Instance().Warnln("Parametro authfile no existe o está vacio, utilizando su valor por defecto", authfile)
	} else {
		authfile = fmt.Sprint(af)
	}

	tlsverify := false
	if tlsv, ok := params["tlsverify"]; ok {
		tlsverify, ok = tlsv.(bool)
		if !ok {
			return nil, fmt.Errorf("El parametro tlsverify debe ser un boolean")
		}
	}

	var tlscacert interface{}
	var tlscert interface{}
	var tlskey interface{}

	if tlsverify {
		tlscacert, ok = params["tlscacert"]
		if !ok || fmt.Sprint(tlscacert) == "" {
			return nil, errors.New("Parametro tlscacert no existe")
		}

		tlscert, ok = params["tlscert"]
		if !ok || fmt.Sprint(tlscert) == "" {
			return nil, errors.New("Parametro tlscert no existe")
		}

		tlskey, ok = params["tlskey"]
		if !ok || fmt.Sprint(tlskey) == "" {
			return nil, errors.New("Parametro tlskey no existe")
		}
	}

	p := parameters{
		address:   fmt.Sprint(address),
		authfile:  authfile,
		tlsverify: tlsverify,
		tlscacert: fmt.Sprint(tlscacert),
		tlscert:   fmt.Sprint(tlscert),
		tlskey:    fmt.Sprint(tlskey),
	}

	return New(p)
}
Beispiel #9
0
func (s *Framework) UndeployInstance(containerID string) error {
	remove := false
	var timeout uint = 10
	logger.Instance().Infoln("Se está iniciando el proceso de undeploy del contenedor", containerID)

	// Un valor de 0 sera interpretado como por defecto
	if timeout == 0 {
		timeout = 10
	}

	logger.Instance().Infoln("Deteniendo el contenedor", containerID)
	err := s.client.StopContainer(containerID, timeout)

	if err != nil {
		switch err.(type) {
		case *docker.NoSuchContainer:
			logger.Instance().Infoln("No se encontró el contenedor", containerID)
			return nil
		case *docker.ContainerNotRunning:
			logger.Instance().Infof("El contenedor %s no estaba corriendo", containerID)
			break
		default:
			return err
		}
	}

	if remove {
		logger.Instance().Infoln("Se inició el proceso de remover el contenedor", containerID)
		opts := docker.RemoveContainerOptions{ID: containerID}
		err = s.client.RemoveContainer(opts)
		if err != nil {
			return err
		}
	}

	return nil
}
Beispiel #10
0
func (helper *Marathon) scaleService(id string, instances int) (*framework.ServiceInformation, error) {
	deploymentId, err := helper.client.ScaleApplicationInstances(id, instances, true)
	if err != nil {
		logger.Instance().Errorf("Failed to Scale the application: %s, error: %s", id, err)
		return nil, err
	} else {
		app, err := helper.client.Application(id)
		if err != nil {
			return nil, err
		} else {
			serviceInformation := helper.getServiceInformationFromApp(app)
			serviceInformation.Instances = helper.getInstancesByVersion(app.Tasks, app.Container.Docker.PortMappings, deploymentId.Version)
			return serviceInformation, nil
		}
	}
}
Beispiel #11
0
func authConfig(authConfigPath string, registry string) (docker.AuthConfiguration, error) {
	var r io.Reader
	var err error

	logger.Instance().Infof("Obteniendo los parámetros de autenticación para el registro %s del archivo %s", registry, authConfigPath)
	if r, err = os.Open(authConfigPath); err != nil {
		return docker.AuthConfiguration{}, err
	}

	var authConfigs *docker.AuthConfigurations

	if authConfigs, err = docker.NewAuthConfigurations(r); err != nil {
		return docker.AuthConfiguration{}, err
	}

	for key := range authConfigs.Configs {
		if key == registry {
			return authConfigs.Configs[registry], nil
		}
	}

	return docker.AuthConfiguration{}, errors.New("No se encontraron las credenciales de autenticación")
}
func NewMarathon(params *Parameters) (*Marathon, error) {
	helper := new(Marathon)
	helper.deployTimeout = params.DeployTimeout
	helper.logEntry = logger.Instance().WithFields(params.LogMetadata)
	helper.dockerCfg = params.DockerCfg

	helper.retryTimes = 3
	if params.RetryTimes != -1 {
		helper.retryTimes = params.RetryTimes
	}

	config := marathon.NewDefaultConfig()
	config.URL = utils.ValidateEndpoint(params.EndpointUrl)

	config.HTTPClient = &http.Client{
		Timeout: (time.Duration(10) * time.Second),
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}

	if params.HTTPBasicAuthUser != "" {
		config.HTTPBasicAuthUser = params.HTTPBasicAuthUser
		config.HTTPBasicPassword = params.HTTPBasicAuthPassword
	}

	client, err := marathon.NewClient(config)
	if err != nil {
		return nil, framework.NewFrameworkClientError(frameworkID, err)
	}

	helper.client = client
	return helper, nil
}
Beispiel #13
0
func (s *Framework) DeployService(serviceConfig framework.ServiceConfig, scale int) (*framework.ServiceInformation, error) {
	labels := map[string]string{
		"image_name": serviceConfig.ImageName,
		"image_tag":  serviceConfig.Tag,
	}

	dockerConfig := docker.Config{
		Image:  serviceConfig.ImageName + ":" + serviceConfig.Tag,
		Env:    serviceConfig.Envs,
		Labels: labels,
	}

	sourcetype := "{{.Name}}"
	if serviceConfig.ServiceID != "" {
		sourcetype = serviceConfig.ServiceID
	}

	dockerHostConfig := docker.HostConfig{
		Binds:           []string{"/var/log/service/:/var/log/service/"},
		CPUShares:       int64(serviceConfig.CPUShares),
		PortBindings:    bindPort(serviceConfig.Publish),
		PublishAllPorts: false,
		Privileged:      false,
		LogConfig: docker.LogConfig{
			Type: "syslog",
			Config: map[string]string{
				"tag":             fmt.Sprintf("{{.ImageName}}|%s|{{.ID}}", sourcetype),
				"syslog-facility": "local1",
			},
		},
	}

	if serviceConfig.Memory != 0 {
		dockerHostConfig.Memory = serviceConfig.Memory
	}

	opts := docker.CreateContainerOptions{
		Config:     &dockerConfig,
		HostConfig: &dockerHostConfig}

	err := s.pullImage(opts.Config.Image)
	if err != nil {
		return nil, err
	}

	logger.Instance().Infoln("Creando el contenedor con imagen", opts.Config.Image)
	container, err := s.client.CreateContainer(opts)
	if err != nil {
		return nil, err
	}
	logger.Instance().Infoln("Contenedor creado... Se inicia el proceso de arranque", container.ID)
	err = s.client.StartContainer(container.ID, nil)
	if err != nil {
		switch err.(type) {
		case *docker.NoSuchContainer:
			return nil, err
		case *docker.ContainerAlreadyRunning:
			logger.Instance().Infof("El contenedor %s ya estaba corriendo", container.ID)
			break
		default:
			return nil, err
		}
	}
	logger.Instance().Infoln("Contenedor corriendo... Inspeccionando sus datos", container.Name)
	criteria := &framework.ImageNameAndImageTagRegexpCriteria{
		FullImageNameRegexp: regexp.MustCompile(serviceConfig.ImageName + ":" + serviceConfig.Tag),
	}

	result, err := s.FindServiceInformation(criteria) // TODO FIX
	if err != nil {
		return nil, err
	} else if len(result) == 0 {
		return nil, errors.New("No hay resultados")
	}

	return result[0], nil
}