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") }
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) }
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...) }
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 }
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") }
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 }
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 }
func (b retryableBlobstore) Validate() error { if b.maxTries < 1 { return bosherr.Error("Max tries must be > 0") } return b.blobstore.Validate() }
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 }
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 }
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 }
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 }
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") }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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]) }
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 }
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) }
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 }
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 }
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 }
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 }
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) }
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 }
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 }