コード例 #1
0
func (r defaultNetworkResolver) GetDefaultNetwork() (boshsettings.Network, error) {
	network := boshsettings.Network{}

	routes, err := r.routesSearcher.SearchRoutes()
	if err != nil {
		return network, bosherr.WrapError(err, "Searching routes")
	}

	if len(routes) == 0 {
		return network, bosherr.Error("No routes found")
	}

	for _, route := range routes {
		if !route.IsDefault() {
			continue
		}

		ip, err := r.ipResolver.GetPrimaryIPv4(route.InterfaceName)
		if err != nil {
			return network, bosherr.WrapErrorf(err, "Getting primary IPv4 for interface '%s'", route.InterfaceName)
		}

		return boshsettings.Network{
			IP:      ip.IP.String(),
			Netmask: gonet.IP(ip.Mask).String(),
			Gateway: route.Gateway,
		}, nil

	}

	return network, bosherr.Error("Failed to find default route")
}
コード例 #2
0
ファイル: runner.go プロジェクト: viovanov/bosh-agent
func (r concreteRunner) Run(action Action, payloadBytes []byte) (value interface{}, err error) {
	payloadArgs, err := r.extractJSONArguments(payloadBytes)
	if err != nil {
		err = bosherr.WrapError(err, "Extracting json arguments")
		return
	}

	actionValue := reflect.ValueOf(action)
	runMethodValue := actionValue.MethodByName("Run")
	if runMethodValue.Kind() != reflect.Func {
		err = bosherr.Error("Run method not found")
		return
	}

	runMethodType := runMethodValue.Type()
	if r.invalidReturnTypes(runMethodType) {
		err = bosherr.Error("Run method should return a value and an error")
		return
	}

	methodArgs, err := r.extractMethodArgs(runMethodType, payloadArgs)
	if err != nil {
		err = bosherr.WrapError(err, "Extracting method arguments from payload")
		return
	}

	values := runMethodValue.Call(methodArgs)
	return r.extractReturns(values)
}
コード例 #3
0
func (f SettingsSourceFactory) buildWithoutRegistry() (boshsettings.Source, error) {
	var settingsSources []boshsettings.Source

	for _, opts := range f.options.Sources {
		var settingsSource boshsettings.Source

		switch typedOpts := opts.(type) {
		case HTTPSourceOptions:
			return nil, bosherr.Error("HTTP source is not supported without registry")

		case ConfigDriveSourceOptions:
			settingsSource = NewConfigDriveSettingsSource(
				typedOpts.DiskPaths,
				typedOpts.MetaDataPath,
				typedOpts.SettingsPath,
				f.platform,
				f.logger,
			)

		case FileSourceOptions:
			return nil, bosherr.Error("File source is not supported without registry")

		case CDROMSourceOptions:
			settingsSource = NewCDROMSettingsSource(
				typedOpts.FileName,
				f.platform,
				f.logger,
			)
		}

		settingsSources = append(settingsSources, settingsSource)
	}

	return NewMultiSettingsSource(settingsSources...)
}
コード例 #4
0
func (a DrainAction) determineParams(drainType DrainType, currentSpec boshas.V1ApplySpec, newSpecs []boshas.V1ApplySpec) (boshdrain.ScriptParams, error) {
	var newSpec *boshas.V1ApplySpec
	var params boshdrain.ScriptParams

	if len(newSpecs) > 0 {
		newSpec = &newSpecs[0]
	}

	switch drainType {
	case DrainTypeStatus:
		// Status was used in the past when dynamic drain was implemented in the Director.
		// Now that we implement it in the agent, we should never get a call for this type.
		return params, bosherr.Error("Unexpected call with drain type 'status'")

	case DrainTypeUpdate:
		if newSpec == nil {
			return params, bosherr.Error("Drain update requires new spec")
		}

		params = boshdrain.NewUpdateParams(currentSpec, *newSpec)

	case DrainTypeShutdown:
		err := a.notifier.NotifyShutdown()
		if err != nil {
			return params, bosherr.WrapError(err, "Notifying shutdown")
		}

		params = boshdrain.NewShutdownParams(currentSpec, newSpec)
	}

	return params, nil
}
コード例 #5
0
ファイル: linux_platform.go プロジェクト: tacgomes/bosh-agent
func (p linux) findRootDevicePath() (string, error) {
	mounts, err := p.diskManager.GetMountsSearcher().SearchMounts()

	if err != nil {
		return "", bosherr.WrapError(err, "Searching mounts")
	}

	for _, mount := range mounts {
		if mount.MountPoint == "/" && strings.HasPrefix(mount.PartitionPath, "/dev/") {
			p.logger.Debug(logTag, "Found root partition: `%s'", mount.PartitionPath)

			stdout, _, _, err := p.cmdRunner.RunCommand("readlink", "-f", mount.PartitionPath)
			if err != nil {
				return "", bosherr.WrapError(err, "Shelling out to readlink")
			}
			rootPartition := strings.Trim(stdout, "\n")
			p.logger.Debug(logTag, "Symlink is: `%s'", rootPartition)

			validRootPartition := regexp.MustCompile(`^/dev/[a-z]+1$`)
			if !validRootPartition.MatchString(rootPartition) {
				return "", bosherr.Error("Root partition is not the first partition")
			}

			return strings.Trim(rootPartition, "1"), nil
		}
	}

	return "", bosherr.Error("Getting root partition device")
}
コード例 #6
0
func (bc FileBundleCollection) Get(definition BundleDefinition) (Bundle, error) {
	if len(definition.BundleName()) == 0 {
		return nil, bosherr.Error("Missing bundle name")
	}

	if len(definition.BundleVersion()) == 0 {
		return nil, bosherr.Error("Missing bundle version")
	}

	installPath := filepath.Join(bc.installPath, bc.name, definition.BundleName(), definition.BundleVersion())
	enablePath := filepath.Join(bc.enablePath, bc.name, definition.BundleName())
	return NewFileBundle(installPath, enablePath, bc.fs, bc.logger), nil
}
コード例 #7
0
func (b localBlobstore) Validate() error {
	path, found := b.options["blobstore_path"]
	if !found {
		return bosherr.Error("missing blobstore_path")
	}

	_, ok := path.(string)
	if !ok {
		return bosherr.Error("blobstore_path must be a string")
	}

	return nil
}
コード例 #8
0
func (b retryableBlobstore) Validate() error {
	if b.maxTries < 1 {
		return bosherr.Error("Max tries must be > 0")
	}

	return b.blobstore.Validate()
}
コード例 #9
0
func (udev ConcreteUdevDevice) readByte(filePath string) error {
	udev.logger.Debug(udev.logtag, "readBytes from file: %s", filePath)
	device, err := os.Open(filePath)
	if err != nil {
		return err
	}
	defer func() {
		if err = device.Close(); err != nil {
			udev.logger.Warn(udev.logtag, "Failed to close device: %s", err.Error())
		}
	}()
	udev.logger.Debug(udev.logtag, "Successfully open file: %s", filePath)

	bytes := make([]byte, 1, 1)
	read, err := device.Read(bytes)
	if err != nil {
		return err
	}
	udev.logger.Debug(udev.logtag, "Successfully read %d bytes from file: %s", read, filePath)

	if read != 1 {
		return bosherr.Error("Device readable but zero length")
	}

	return nil
}
コード例 #10
0
ファイル: file_bundle.go プロジェクト: viovanov/bosh-agent
func (b FileBundle) GetInstallPath() (boshsys.FileSystem, string, error) {
	path := b.installPath
	if !b.fs.FileExists(path) {
		return nil, "", bosherr.Error("install dir does not exist")
	}

	return b.fs, path, nil
}
コード例 #11
0
func (ms *configDriveMetadataService) GetInstanceID() (string, error) {
	if ms.metaDataContents.InstanceID == "" {
		return "", bosherr.Error("Failed to load instance-id from config drive metadata service")
	}

	ms.logger.Debug(ms.logTag, "Getting instance id: %s", ms.metaDataContents.InstanceID)
	return ms.metaDataContents.InstanceID, nil
}
コード例 #12
0
func (ms *configDriveMetadataService) GetServerName() (string, error) {
	if ms.userDataContents.Server.Name == "" {
		return "", bosherr.Error("Failed to load server name from config drive metadata service")
	}

	ms.logger.Debug(ms.logTag, "Getting server name: %s", ms.userDataContents.Server.Name)
	return ms.userDataContents.Server.Name, nil
}
コード例 #13
0
func (ms *configDriveMetadataService) GetPublicKey() (string, error) {
	if firstPublicKey, ok := ms.metaDataContents.PublicKeys["0"]; ok {
		if openSSHKey, ok := firstPublicKey["openssh-key"]; ok {
			return openSSHKey, nil
		}
	}

	return "", bosherr.Error("Failed to load openssh-key from config drive metadata service")
}
コード例 #14
0
func NewMultiSettingsSource(sources ...boshsettings.Source) (boshsettings.Source, error) {
	var err error

	if len(sources) == 0 {
		err = bosherr.Error("MultiSettingsSource requires to have at least one source")
	}

	return &MultiSettingsSource{sources: sources}, err
}
コード例 #15
0
func (d *dummyNatsJobSupervisor) Start() error {
	if d.status == "fail_task" {
		return bosherror.Error("fake-task-fail-error")
	}
	if d.status != "failing" {
		d.status = "running"
	}
	return nil
}
コード例 #16
0
ファイル: runner.go プロジェクト: viovanov/bosh-agent
func (r concreteRunner) extractReturns(values []reflect.Value) (value interface{}, err error) {
	errValue := values[1]
	if !errValue.IsNil() {
		errorValues := errValue.MethodByName("Error").Call([]reflect.Value{})
		err = bosherr.Error(errorValues[0].String())
	}

	value = values[0].Interface()
	return
}
コード例 #17
0
func BuildErrorWithJSON(msg string, logger boshlog.Logger) ([]byte, error) {
	response := NewExceptionResponse(bosherr.Error(msg))

	respJSON, err := json.Marshal(response)
	if err != nil {
		return respJSON, bosherr.WrapError(err, "Marshalling JSON")
	}

	logger.Info(mbusHandlerLogTag, "Building error", msg)

	return respJSON, nil
}
コード例 #18
0
func (udev ConcreteUdevDevice) Trigger() (err error) {
	udev.logger.Debug(udev.logtag, "Triggering UdevDevice")
	switch {
	case udev.runner.CommandExists("udevadm"):
		_, _, _, err = udev.runner.RunCommand("udevadm", "trigger")
	case udev.runner.CommandExists("udevtrigger"):
		_, _, _, err = udev.runner.RunCommand("udevtrigger")
	default:
		err = bosherr.Error("can not find udevadm or udevtrigger commands")
	}
	return
}
コード例 #19
0
func (ms httpMetadataService) GetServerName() (string, error) {
	userData, err := ms.getUserData()
	if err != nil {
		return "", bosherr.WrapError(err, "Getting user data")
	}

	serverName := userData.Server.Name

	if len(serverName) == 0 {
		return "", bosherr.Error("Empty server name")
	}

	return serverName, nil
}
コード例 #20
0
ファイル: downloader.go プロジェクト: viovanov/bosh-agent
func (d *Downloader) httpClient() (*http.Client, error) {
	certPool := x509.NewCertPool()
	if !certPool.AppendCertsFromPEM(([]byte)(d.config.CACertPem)) {
		return nil, errors.Error("Failed to load CA cert")
	}

	tr := &http.Transport{
		TLSClientConfig: &tls.Config{
			RootCAs:    certPool,
			ClientAuth: tls.RequireAndVerifyClientCert,
		},
	}

	return &http.Client{Transport: tr}, nil
}
コード例 #21
0
func compareStrs(pattern, name []string) (bool, error) {
	if len(pattern) == 0 {
		return true, nil
	}

	if len(pattern) > 1 || len(name) > 1 {
		return false, errors.Error("Multiple entries in x509 records not supported")
	}

	if len(name) != 1 {
		return false, nil
	}

	return compareStr(pattern[0], name[0])
}
コード例 #22
0
ファイル: run_errand.go プロジェクト: viovanov/bosh-agent
func (a RunErrandAction) Run() (ErrandResult, error) {
	currentSpec, err := a.specService.Get()
	if err != nil {
		return ErrandResult{}, bosherr.WrapError(err, "Getting current spec")
	}

	if len(currentSpec.JobSpec.Template) == 0 {
		return ErrandResult{}, bosherr.Error("At least one job template is required to run an errand")
	}

	command := boshsys.Command{
		Name: filepath.Join(a.jobsDir, currentSpec.JobSpec.Template, "bin", "run"),
		Env: map[string]string{
			"PATH": "/usr/sbin:/usr/bin:/sbin:/bin",
		},
	}

	process, err := a.cmdRunner.RunComplexCommandAsync(command)
	if err != nil {
		return ErrandResult{}, bosherr.WrapError(err, "Running errand script")
	}

	var result boshsys.Result

	// Can only wait once on a process but cancelling can happen multiple times
	for processExitedCh := process.Wait(); processExitedCh != nil; {
		select {
		case result = <-processExitedCh:
			processExitedCh = nil
		case <-a.cancelCh:
			// Ignore possible TerminateNicely error since we cannot return it
			err := process.TerminateNicely(10 * time.Second)
			if err != nil {
				a.logger.Error(runErrandActionLogTag, "Failed to terminate %s", err.Error())
			}
		}
	}

	if result.Error != nil && result.ExitStatus == -1 {
		return ErrandResult{}, bosherr.WrapError(result.Error, "Running errand script")
	}

	return ErrandResult{
		Stdout:     result.Stdout,
		Stderr:     result.Stderr,
		ExitStatus: result.ExitStatus,
	}, nil
}
コード例 #23
0
func (p *CertificateVerifier) Verify(peerCertificates []*x509.Certificate) error {
	if len(peerCertificates) < 1 {
		return errors.Error("No peer certificates provided by client")
	}
	subject := peerCertificates[0].Subject
	for _, pattern := range p.AllowedNames {
		matched, err := matchName(&pattern, &subject)
		if err != nil {
			return err
		}
		if matched {
			return nil
		}
	}
	return errors.Errorf("Subject (%#v) didn't match allowed distinguished names", subject)
}
コード例 #24
0
ファイル: ssl_config.go プロジェクト: tacgomes/bosh-agent
func parseNames(allowedNames []string) ([]pkix.Name, error) {
	if len(allowedNames) == 0 {
		return nil, errors.Error("AllowedNames must be specified")
	}

	var pkixNames []pkix.Name
	parser := NewDistinguishedNamesParser()
	for _, dn := range allowedNames {
		pkixName, err := parser.Parse(dn)
		if err != nil {
			return nil, errors.WrapError(err, "Invalid AllowedNames")
		}
		pkixNames = append(pkixNames, *pkixName)
	}

	return pkixNames, nil
}
コード例 #25
0
ファイル: fetch_logs.go プロジェクト: viovanov/bosh-agent
func (a FetchLogsAction) Run(logType string, filters []string) (value map[string]string, err error) {
	var logsDir string

	switch logType {
	case "job":
		if len(filters) == 0 {
			filters = []string{"**/*"}
		}
		logsDir = filepath.Join(a.settingsDir.BaseDir(), "sys", "log")
	case "agent":
		if len(filters) == 0 {
			filters = []string{"**/*"}
		}
		logsDir = filepath.Join(a.settingsDir.BaseDir(), "bosh", "log")
	default:
		err = bosherr.Error("Invalid log type")
		return
	}

	tmpDir, err := a.copier.FilteredCopyToTemp(logsDir, filters)
	if err != nil {
		err = bosherr.WrapError(err, "Copying filtered files to temp directory")
		return
	}

	defer a.copier.CleanUp(tmpDir)

	tarball, err := a.compressor.CompressFilesInDir(tmpDir)
	if err != nil {
		err = bosherr.WrapError(err, "Making logs tarball")
		return
	}

	defer func() {
		_ = a.compressor.CleanUp(tarball)
	}()

	blobID, _, err := a.blobstore.Create(tarball)
	if err != nil {
		err = bosherr.WrapError(err, "Create file on blobstore")
		return
	}

	value = map[string]string{"blobstore_id": blobID}
	return
}
コード例 #26
0
func (f SettingsSourceFactory) buildWithRegistry() (boshsettings.Source, error) {
	var metadataServices []MetadataService

	digDNSResolver := NewDigDNSResolver(f.platform.GetRunner(), f.logger)
	resolver := NewRegistryEndpointResolver(digDNSResolver)

	for _, opts := range f.options.Sources {
		var metadataService MetadataService

		switch typedOpts := opts.(type) {
		case HTTPSourceOptions:
			metadataService = NewHTTPMetadataService(typedOpts.URI, resolver, f.platform, f.logger)

		case ConfigDriveSourceOptions:
			metadataService = NewConfigDriveMetadataService(
				resolver,
				f.platform,
				typedOpts.DiskPaths,
				typedOpts.MetaDataPath,
				typedOpts.UserDataPath,
				f.logger,
			)

		case FileSourceOptions:
			metadataService = NewFileMetadataService(
				typedOpts.MetaDataPath,
				typedOpts.UserDataPath,
				typedOpts.SettingsPath,
				f.platform.GetFs(),
				f.logger,
			)

		case CDROMSourceOptions:
			return nil, bosherr.Error("CDROM source is not supported when registry is used")
		}

		metadataServices = append(metadataServices, metadataService)
	}

	metadataService := NewMultiSourceMetadataService(metadataServices...)
	registryProvider := NewRegistryProvider(metadataService, f.platform, f.options.UseServerName, f.platform.GetFs(), f.logger)
	settingsSource := NewComplexSettingsSource(metadataService, registryProvider, f.logger)

	return settingsSource, nil
}
コード例 #27
0
func (s *SourceOptionsSlice) UnmarshalJSON(data []byte) error {
	var maps []map[string]interface{}

	err := json.Unmarshal(data, &maps)
	if err != nil {
		return bosherr.WrapError(err, "Unmarshalling sources")
	}

	for _, m := range maps {
		if optType, ok := m["Type"]; ok {
			var err error
			var opts SourceOptions

			switch {
			case optType == "HTTP":
				var o HTTPSourceOptions
				err, opts = mapstruc.Decode(m, &o), o

			case optType == "ConfigDrive":
				var o ConfigDriveSourceOptions
				err, opts = mapstruc.Decode(m, &o), o

			case optType == "File":
				var o FileSourceOptions
				err, opts = mapstruc.Decode(m, &o), o

			case optType == "CDROM":
				var o CDROMSourceOptions
				err, opts = mapstruc.Decode(m, &o), o

			default:
				err = bosherr.Errorf("Unknown source type '%s'", optType)
			}

			if err != nil {
				return bosherr.WrapErrorf(err, "Unmarshalling source type '%s'", optType)
			}
			*s = append(*s, opts)
		} else {
			return bosherr.Error("Missing source type")
		}
	}

	return nil
}
コード例 #28
0
ファイル: ssl_handler.go プロジェクト: tacgomes/bosh-agent
func (h *sslHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	var err error
	if req.TLS == nil {
		err = errors.Error("Not SSL")
	}

	if err == nil {
		err = h.certificateVerifier.Verify(req.TLS.PeerCertificates)
	}

	if err != nil {
		rw.WriteHeader(http.StatusUnauthorized)
		h.logger.Error(fmt.Sprintf("%T", h), errors.WrapError(err, "Unauthorized access").Error())
		return
	}

	h.delegate.ServeHTTP(rw, req)
}
コード例 #29
0
ファイル: linux_platform.go プロジェクト: tacgomes/bosh-agent
func (p linux) GetMonitCredentials() (username, password string, err error) {
	monitUserFilePath := filepath.Join(p.dirProvider.BaseDir(), "monit", "monit.user")
	credContent, err := p.fs.ReadFileString(monitUserFilePath)
	if err != nil {
		err = bosherr.WrapError(err, "Reading monit user file")
		return
	}

	credParts := strings.SplitN(credContent, ":", 2)
	if len(credParts) != 2 {
		err = bosherr.Error("Malformated monit user file, expecting username and password separated by ':'")
		return
	}

	username = credParts[0]
	password = credParts[1]
	return
}
コード例 #30
0
ファイル: runner.go プロジェクト: viovanov/bosh-agent
func (r concreteRunner) invalidReturnTypes(methodType reflect.Type) (valid bool) {
	if methodType.NumOut() != 2 {
		return true
	}

	secondReturnType := methodType.Out(1)
	if secondReturnType.Kind() != reflect.Interface {
		return true
	}

	errorType := reflect.TypeOf(bosherr.Error(""))
	secondReturnIsError := errorType.Implements(secondReturnType)
	if !secondReturnIsError {
		return true
	}

	return
}