// Export enables an NFS export on the cluster to access the volumes.  Return the path to the export
// so other processes can mount the volume directory
184232
func Export(
	ctx context.Context,
	client api.Client,
	path string) (err error) {
	// PAPI call: POST https://1.2.3.4:8080/platform/1/protocols/nfs/exports/
	//            Content-Type: application/json
	//            {paths: ["/path/to/volume"]}

	if path == "" {
		return errors.New("no path set")
	}

	var data = &ExportPathList{Paths: []string{path}}
	data.MapAll.User = client.User()
	if group := client.Group(); group != "" {
		data.MapAll.Groups = append(data.MapAll.Groups, group)
	}
	var resp *postIsiExportResp

	err = client.Post(ctx, exportsPath, "", nil, nil, data, &resp)

	if err != nil {
		return err
	}

	return nil
}
756734
func (d *driver) getNFSPath(v *api.Volume) (string, error) {
	locator := v.GetLocator()
	server, ok := locator.VolumeLabels["server"]
	if !ok {
		logrus.Warnf("No server label found on volume")
		return "", fmt.Errorf("No server label found on volume: " + v.Id)
	}

	return path.Join(nfsMountPath, server), nil
}
549995
func (s *Set) Export() (JSONMetric, error) {
	val, err := s.Hll.MarshalBinary()
	if err != nil {
		return JSONMetric{}, err
	}
	return JSONMetric{
		MetricKey: MetricKey{
			Name:       s.Name,
			Type:       "set",
			JoinedTags: strings.Join(s.Tags, ","),
		},
		Tags:  s.Tags,
		Value: val,
	}, nil
}
815128
func (s *StatusCheck) Export() (JSONMetric, error) {
	var buf bytes.Buffer

	err := binary.Write(&buf, binary.LittleEndian, s.Value)
	if err != nil {
		return JSONMetric{}, err
	}

	return JSONMetric{
		MetricKey: MetricKey{
			Name:       s.Name,
			Type:       "status",
			JoinedTags: strings.Join(s.Tags, ","),
		},
		Tags:  s.Tags,
		Value: buf.Bytes(),
	}, nil
}
252067
func (c *Client) Mount(source, destination string) error {
	return nfsMount(&nfs.NFSDriver{}, path.Join(c.exportedPath, source), destination)
}
435323
func (v *DeviceMapperVolume) Export(label, parent string, writer io.Writer, excludes []string) error {
	glog.V(2).Infof("Export() (%s) START", v.name)
	defer glog.V(2).Infof("Export() (%s) END", v.name)
	if !v.snapshotExists(label) {
		return volume.ErrSnapshotDoesNotExist
	}
	label = v.rawSnapshotLabel(label)
	mountpoint, err := ioutil.TempDir("", "serviced-export-volume-")
	if err != nil {
		return err
	}
	defer os.RemoveAll(mountpoint)
	deviceHash, err := v.Metadata.LookupSnapshotDevice(label)
	if err != nil {
		return err
	}
	glog.V(2).Infof("Mounting temporary export device %s", deviceHash)
	if err := v.driver.DeviceSet.MountDevice(deviceHash, mountpoint, label); err != nil {
		return err
	}
	defer func(d *DeviceMapperDriver, deviceHash, mountpoint string) {
		// We use the provided UnmountDevice func here, rather than our own
		// unmount(), because we DO care about Docker's internal bookkeeping
		// here. Without this, DeviceSet.DeleteDevice will fail.
		if err := d.DeviceSet.UnmountDevice(deviceHash, mountpoint); err != nil {
			glog.V(2).Infof("Error unmounting %s (device: %s): %s", mountpoint, deviceHash, err)
		}
		d.DeviceSet.Lock()
		if err := d.DeactivateDevice(deviceHash); err != nil {
			glog.V(2).Infof("Error deactivating device %s: %s", deviceHash, err)
		}
		d.DeviceSet.Unlock()
	}(v.driver, deviceHash, mountpoint)

	tarOut := tar.NewWriter(writer)

	// Set the driver type
	drivertype := []byte(v.Driver().DriverType())
	header := &tar.Header{Name: fmt.Sprintf("%s-driver", label), Size: int64(len(drivertype))}
	if err := tarOut.WriteHeader(header); err != nil {
		glog.Errorf("Could not export driver type header for snapshot %s: %s", label, err)
		return err
	}
	if _, err := tarOut.Write(drivertype); err != nil {
		glog.Errorf("Could not export driver type for snapshot %s: %s", label, err)
		return err
	}

	// Set the device metadata
	size, err := v.SizeOf()
	if err != nil {
		glog.Errorf("Could not get the size of the device for snapshot %s: %s", label, err)
		return err
	}
	volInfo, err := json.Marshal(volumeInfo{Size: size})
	if err != nil {
		glog.Errorf("Could not marshal device info for snapshot %s: %s", label, err)
		return err
	}
	header = &tar.Header{Name: fmt.Sprintf("%s-device", label), Size: int64(len(volInfo))}
	if err := tarOut.WriteHeader(header); err != nil {
		glog.Errorf("Could not export device info header for snapshot %s: %s", label, err)
		return err
	}
	if _, err := tarOut.Write(volInfo); err != nil {
		glog.Errorf("Could not export device info for snapshot %s: %s", label, err)
		return err
	}

	// Write metadata
	mdpath := filepath.Join(v.driver.MetadataDir(), label)

	if err := exportDirectoryAsTar(mdpath, fmt.Sprintf("%s-metadata", label), tarOut, []string{}); err != nil {
		return err
	}
	if err := exportDirectoryAsTar(mountpoint, fmt.Sprintf("%s-volume", label), tarOut, excludes); err != nil {
		return err
	}

	return tarOut.Close()
}
334741
func (bk *Backend) Export() ([]backend.Item, error) {
	var out []backend.Item

	// Get a list of all buckets in the backend.
	files, err := ioutil.ReadDir(path.Join(bk.rootDir))
	if err != nil {
		return nil, trace.ConvertSystemError(err)
	}

	// Loop over all buckets in the backend.
	for _, fi := range files {
		// skip sqlite database file - (in general sense,
		// dir backend lacked ability to skip files that
		// are present in the directory, so this is a necessary
		// evil that is going away with dir backend)
		if filepath.Base(fi.Name()) == "sqlite.db" {
			continue
		}
		pathToBucket := bk.pathToBucket(fi.Name())
		bucketParts, err := decodeBucket(filepath.Base(fi.Name()))
		if err != nil {
			return nil, trace.Wrap(err)
		}

		// Open the bucket to work on the items.
		b, err := bk.openBucket(pathToBucket, os.O_RDWR)
		if err != nil {
			return nil, trace.Wrap(err)
		}
		defer b.Close()

		// Loop over all keys, flatten them, and return key and value to caller.
		for k, v := range b.items {
			// If the bucket item is expired, update the bucket, and don't include
			// it in the output.
			if bk.isExpired(v) {
				b.deleteItem(k)
				continue
			}

			flatKey := make([]string, len(bucketParts))
			copy(flatKey, bucketParts)
			flatKey = append(flatKey, k)
			out = append(out, backend.Item{
				Key:     backend.Key(flatKey...),
				Value:   v.Value,
				Expires: v.ExpiryTime,
			})

		}
	}

	// Sort items and remove any duplicates.
	sort.Slice(out, func(i, j int) bool {
		return bytes.Compare(out[i].Key, out[j].Key) < 0
	})
	out = removeBackendDuplicates(out)

	return out, nil
}
1084810
func (h *Histo) Export() (JSONMetric, error) {
	val, err := h.Value.GobEncode()
	if err != nil {
		return JSONMetric{}, err
	}
	return JSONMetric{
		MetricKey: MetricKey{
			Name:       h.Name,
			Type:       "histogram",
			JoinedTags: strings.Join(h.Tags, ","),
		},
		Tags:  h.Tags,
		Value: val,
	}, nil
}
950244
func (ir *IdentifyOutcome) Export(g *GlobalContext) *keybase1.IdentifyOutcome {
	v := make([]string, len(ir.Warnings))
	for i, w := range ir.Warnings {
		v[i] = w.Warning()
	}
	del := make([]keybase1.TrackDiff, len(ir.Revoked))
	for i, d := range ir.Revoked {
		del[i] = *ExportTrackDiff(d)
	}
	ret := &keybase1.IdentifyOutcome{
		Username:          ir.Username.String(),
		Status:            ExportErrorAsStatus(g, ir.Error),
		Warnings:          v,
		TrackUsed:         ExportTrackSummary(ir.TrackUsed, ir.Username.String()),
		TrackStatus:       ir.TrackStatus(),
		NumTrackFailures:  ir.NumTrackFailures(),
		NumTrackChanges:   ir.NumTrackChanges(),
		NumProofFailures:  ir.NumProofFailures(),
		NumRevoked:        ir.NumRevoked(),
		NumProofSuccesses: ir.NumProofSuccesses(),
		Revoked:           del,
		TrackOptions:      ir.TrackOptions,
		Reason:            ir.Reason,
	}
	return ret
}
928025
func (api *API) export(serviceName string,
	session *session.Session,
	S3Bucket string,
	S3Key string,
	S3Version string,
	roleNameMap map[string]*gocf.StringExpr,
	template *gocf.Template,
	noop bool,
	logger *logrus.Logger) error {

	apiGatewayResourceNameForPath := func(fullPath string) string {
		pathParts := strings.Split(fullPath, "/")
		return CloudFormationResourceName("%sResource", pathParts[0], fullPath)
	}

	// Create an API gateway entry
	apiGatewayRes := &gocf.APIGatewayRestAPI{
		Description:    gocf.String(api.Description),
		FailOnWarnings: gocf.Bool(false),
		Name:           gocf.String(api.name),
	}
	if api.CloneFrom != "" {
		apiGatewayRes.CloneFrom = gocf.String(api.CloneFrom)
	}
	if api.Description == "" {
		apiGatewayRes.Description = gocf.String(fmt.Sprintf("%s RestApi", serviceName))
	} else {
		apiGatewayRes.Description = gocf.String(api.Description)
	}
	apiGatewayResName := api.LogicalResourceName()
	// Is there an endpoint type?
	if api.EndpointConfiguration != nil {
		apiGatewayRes.EndpointConfiguration = api.EndpointConfiguration
	}
	template.AddResource(apiGatewayResName, apiGatewayRes)
	apiGatewayRestAPIID := gocf.Ref(apiGatewayResName)

	// List of all the method resources we're creating s.t. the
	// deployment can DependOn them
	optionsMethodPathMap := make(map[string]bool)
	var apiMethodCloudFormationResources []string
	for eachResourceMethodKey, eachResourceDef := range api.resources {
		// First walk all the user resources and create intermediate paths
		// to repreesent all the resources
		var parentResource *gocf.StringExpr
		pathParts := strings.Split(strings.TrimLeft(eachResourceDef.pathPart, "/"), "/")
		pathAccumulator := []string{"/"}
		for index, eachPathPart := range pathParts {
			pathAccumulator = append(pathAccumulator, eachPathPart)
			resourcePathName := apiGatewayResourceNameForPath(strings.Join(pathAccumulator, "/"))
			if _, exists := template.Resources[resourcePathName]; !exists {
				cfResource := &gocf.APIGatewayResource{
					RestAPIID: apiGatewayRestAPIID.String(),
					PathPart:  gocf.String(eachPathPart),
				}
				if index <= 0 {
					cfResource.ParentID = gocf.GetAtt(apiGatewayResName, "RootResourceId")
				} else {
					cfResource.ParentID = parentResource
				}
				template.AddResource(resourcePathName, cfResource)
			}
			parentResource = gocf.Ref(resourcePathName).String()
		}

		// Add the lambda permission
		apiGatewayPermissionResourceName := CloudFormationResourceName("APIGatewayLambdaPerm",
			eachResourceMethodKey)
		lambdaInvokePermission := &gocf.LambdaPermission{
			Action:       gocf.String("lambda:InvokeFunction"),
			FunctionName: gocf.GetAtt(eachResourceDef.parentLambda.LogicalResourceName(), "Arn"),
			Principal:    gocf.String(APIGatewayPrincipal),
		}
		template.AddResource(apiGatewayPermissionResourceName, lambdaInvokePermission)

		// BEGIN CORS - OPTIONS verb
		// CORS is API global, but it's possible that there are multiple different lambda functions
		// that are handling the same HTTP resource. In this case, track whether we've already created an
		// OPTIONS entry for this path and only append iff this is the first time through
		if api.corsEnabled() {
			methodResourceName := CloudFormationResourceName(fmt.Sprintf("%s-OPTIONS",
				eachResourceDef.pathPart), eachResourceDef.pathPart)
			_, resourceExists := optionsMethodPathMap[methodResourceName]
			if !resourceExists {
				template.AddResource(methodResourceName, corsOptionsGatewayMethod(api,
					apiGatewayRestAPIID,
					parentResource))
				apiMethodCloudFormationResources = append(apiMethodCloudFormationResources, methodResourceName)
				optionsMethodPathMap[methodResourceName] = true
			}
		}
		// END CORS - OPTIONS verb

		// BEGIN - user defined verbs
		for eachMethodName, eachMethodDef := range eachResourceDef.Methods {

			methodRequestTemplates, methodRequestTemplatesErr := methodRequestTemplates(eachMethodDef)
			if methodRequestTemplatesErr != nil {
				return methodRequestTemplatesErr
			}
			apiGatewayMethod := &gocf.APIGatewayMethod{
				HTTPMethod: gocf.String(eachMethodName),
				ResourceID: parentResource.String(),
				RestAPIID:  apiGatewayRestAPIID.String(),
				Integration: &gocf.APIGatewayMethodIntegration{
					IntegrationHTTPMethod: gocf.String("POST"),
					Type:                  gocf.String("AWS"),
					RequestTemplates:      methodRequestTemplates,
					URI: gocf.Join("",
						gocf.String("arn:aws:apigateway:"),
						gocf.Ref("AWS::Region"),
						gocf.String(":lambda:path/2015-03-31/functions/"),
						gocf.GetAtt(eachResourceDef.parentLambda.LogicalResourceName(), "Arn"),
						gocf.String("/invocations")),
				},
			}
			// Handle authorization
			if eachMethodDef.authorizationID != nil {
				// See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-method.html#cfn-apigateway-method-authorizationtype
				apiGatewayMethod.AuthorizationType = gocf.String("CUSTOM")
				apiGatewayMethod.AuthorizerID = eachMethodDef.authorizationID.String()
			} else {
				apiGatewayMethod.AuthorizationType = gocf.String("NONE")
			}
			if len(eachMethodDef.Parameters) != 0 {
				requestParams := make(map[string]string)
				for eachKey, eachBool := range eachMethodDef.Parameters {
					requestParams[eachKey] = fmt.Sprintf("%t", eachBool)
				}
				apiGatewayMethod.RequestParameters = requestParams
			}

			// Add the integration response RegExps
			apiGatewayMethod.Integration.IntegrationResponses = integrationResponses(api,
				eachMethodDef.Integration.Responses,
				api.corsEnabled())

			// Add outbound method responses
			apiGatewayMethod.MethodResponses = methodResponses(api,
				eachMethodDef.Responses,
				api.corsEnabled())

			prefix := fmt.Sprintf("%s%s", eachMethodDef.httpMethod, eachResourceMethodKey)
			methodResourceName := CloudFormationResourceName(prefix, eachResourceMethodKey, serviceName)
			res := template.AddResource(methodResourceName, apiGatewayMethod)
			res.DependsOn = append(res.DependsOn, apiGatewayPermissionResourceName)
			apiMethodCloudFormationResources = append(apiMethodCloudFormationResources,
				methodResourceName)
		}
	}
	// END

	if nil != api.stage {
		// Is the stack already deployed?
		stageName := api.stage.name
		stageInfo, stageInfoErr := apiStageInfo(api.name,
			stageName,
			session,
			noop,
			logger)
		if nil != stageInfoErr {
			return stageInfoErr
		}
		if nil == stageInfo {
			// Use a stable identifier so that we can update the existing deployment
			apiDeploymentResName := CloudFormationResourceName("APIGatewayDeployment",
				serviceName)
			apiDeployment := &gocf.APIGatewayDeployment{
				Description: gocf.String(api.stage.Description),
				RestAPIID:   apiGatewayRestAPIID.String(),
				StageName:   gocf.String(stageName),
				StageDescription: &gocf.APIGatewayDeploymentStageDescription{
					Description: gocf.String(api.stage.Description),
					Variables:   api.stage.Variables,
				},
			}
			if api.stage.CacheClusterEnabled {
				apiDeployment.StageDescription.CacheClusterEnabled =
					gocf.Bool(api.stage.CacheClusterEnabled)
			}
			if api.stage.CacheClusterSize != "" {
				apiDeployment.StageDescription.CacheClusterSize =
					gocf.String(api.stage.CacheClusterSize)
			}
			deployment := template.AddResource(apiDeploymentResName, apiDeployment)
			deployment.DependsOn = append(deployment.DependsOn, apiMethodCloudFormationResources...)
			deployment.DependsOn = append(deployment.DependsOn, apiGatewayResName)
		} else {
			newDeployment := &gocf.APIGatewayDeployment{
				Description: gocf.String("Deployment"),
				RestAPIID:   apiGatewayRestAPIID.String(),
			}
			if stageInfo.StageName != nil {
				newDeployment.StageName = gocf.String(*stageInfo.StageName)
			}
			// Use an unstable ID s.t. we can actually create a new deployment event.  Not sure how this
			// is going to work with deletes...
			deploymentResName := CloudFormationResourceName("APIGatewayDeployment")
			deployment := template.AddResource(deploymentResName, newDeployment)
			deployment.DependsOn = append(deployment.DependsOn, apiMethodCloudFormationResources...)
			deployment.DependsOn = append(deployment.DependsOn, apiGatewayResName)
		}
		template.Outputs[OutputAPIGatewayURL] = &gocf.Output{
			Description: "API Gateway URL",
			Value: gocf.Join("",
				gocf.String("https://"),
				apiGatewayRestAPIID,
				gocf.String(".execute-api."),
				gocf.Ref("AWS::Region"),
				gocf.String(".amazonaws.com/"),
				gocf.String(stageName)),
		}
	}
	return nil
}
965490
func (c *Client) Export(ctx context.Context, name string) (int, error) {

	ok, id, err := c.IsExported(ctx, name)
	if err != nil {
		return 0, err
	}
	if ok {
		return id, nil
	}

	paths := []string{c.API.VolumePath(name)}

	return api.ExportCreate(
		ctx, c.API,
		&api.Export{Paths: &paths})
}
1080334
func (c *Certificate) Export() ([]byte, error) {
	pemBlock := &pem.Block{
		Type:    certificatePEMBlockType,
		Headers: nil,
		Bytes:   c.derBytes,
	}

	buf := new(bytes.Buffer)
	if err := pem.Encode(buf, pemBlock); err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
50119
func (v *BtrfsVolume) Export(label, parent string, writer io.Writer, excludes []string) error {
	if len(excludes) > 0 {
		glog.Warning("btrfs backups do not support excluding directories")
	}
	if label = strings.TrimSpace(label); label == "" {
		glog.Errorf("%s: label cannot be empty", volume.DriverTypeBtrFS)
		return ErrBtrfsInvalidLabel
	} else if exists, err := v.snapshotExists(label); err != nil {
		return err
	} else if !exists {
		return volume.ErrSnapshotDoesNotExist
	}
	// TODO: add to tarfile and include metadata
	if err := runBtrfsSend(writer, v.sudoer, parent, v.snapshotPath(label)); err != nil {
		glog.Errorf("Could not export snapshot %s: %s", label, err)
		return err
	}
	return nil
}
672137
func (c *Context) Export(name string, value string) {
	c.Lock()
	defer c.Unlock()
	c.vars = append(c.vars, name+"="+value)
}
491185
func (dfs *DistributedFilesystem) Backup(data BackupInfo, w io.Writer) error {

	backupLogger := plog.WithFields(log.Fields{
		"backupversion": data.BackupVersion,
		"timestamp":     data.Timestamp,
	})

	progress := NewProgressCounter(300)
	progress.Log = func() { plog.Infof("Written %v bytes to archive for backup", progress.Total) }

	tarOut := tar.NewWriter(io.MultiWriter(w, progress))

	// write the backup metadata
	if err := dfs.writeBackupMetadata(data, tarOut); err != nil {
		plog.WithError(err).Error("Unable to write metadata for backup")
		return err
	}

	var images []string

	baseImageLogger := backupLogger.WithField("total", len(data.BaseImages))
	baseImageLogger.Info("Preparing docker images for backup")

	// download the base images
	for i, image := range data.BaseImages {
		baseImageLogger = baseImageLogger.WithFields(log.Fields{
			"image":          image,
			"numbercomplete": i + 1,
		})

		if _, err := dfs.docker.FindImage(image); docker.IsImageNotFound(err) {
			if err := dfs.docker.PullImage(image); docker.IsImageNotFound(err) {
				baseImageLogger.Warn("Could not pull base image for backup, skipping")
				continue
			} else if err != nil {
				baseImageLogger.WithError(err).Error("Could not pull image for backup")
				return err
			}
		} else if err != nil {
			baseImageLogger.WithError(err).Error("Could not find image for backup")
			return err
		}

		baseImageLogger.Info("Prepared Docker image for backup")

		images = append(images, image)
	}

	numberOfSnapshots := len(data.Snapshots)

	backupLogger.WithField("total", numberOfSnapshots).Info("Preparing snapshots for backup")

	// export the snapshots
	for i, snapshot := range data.Snapshots {
		vol, info, err := dfs.getSnapshotVolumeAndInfo(snapshot)
		if err != nil {
			return err
		}

		// load the images from this snapshot
		tenantLogger := backupLogger.WithField("tenant", info.TenantID)
		tenantLogger.Info("Preparing images for tenant")

		r, err := vol.ReadMetadata(info.Label, ImagesMetadataFile)
		if err != nil {
			tenantLogger.WithError(err).Error("Could not receive images metadata for tenant")
			return err
		}

		var imgs []string
		if err := importJSON(r, &imgs); err != nil {
			tenantLogger.WithError(err).Error("Could not interpret images metadata for tenant")
			return err
		}

		timer := time.NewTimer(0)
		for _, img := range imgs {
			tenantImageLogger := tenantLogger.WithField("image", img)

			timer.Reset(dfs.timeout)
			if err := dfs.reg.PullImage(timer.C, img); err != nil {
				tenantImageLogger.WithError(err).Error("Could not pull image from registry")
				return err
			}

			image, err := dfs.reg.ImagePath(img)
			if err != nil {
				tenantImageLogger.WithError(err).Error("Could not get the image path from registry")
				return err
			}

			plog.WithField("image", image).Info("Prepared Docker image for backup")

			images = append(images, image)
		}

		timer.Stop()

		snapshotLogger := backupLogger.WithField("snapshot", snapshot)

		// dump the snapshot into the backup
		prefix := path.Join(SnapshotsMetadataDir, info.TenantID, info.Label)
		snapReader, errchan := dfs.snapshotSavePipe(vol, info.Label, data.SnapshotExcludes[snapshot])
		if err := rewriteTar(prefix, tarOut, snapReader); err != nil {
			// be a good citizen and clean up any running threads
			<-errchan
			snapshotLogger.WithError(err).Error("Could not write snapshot to backup")
			return err
		} else if err := <-errchan; err != nil {
			snapshotLogger.WithError(err).Error("Could not export snapshot for backup")
			return err
		}

		snapshotLogger.WithFields(log.Fields{
			"numbercomplete": i + 1,
			"total":          numberOfSnapshots,
		}).Info("Exported snapshot to backup")
	}

	// dump the images from all the snapshots into the backup
	imageReader, errchan := dfs.dockerSavePipe(images...)
	imageLogger := backupLogger.WithField("images", images)
	imageLogger.Info("Starting export of images to backup")
	if err := rewriteTar(DockerImagesFile, tarOut, imageReader); err != nil {
		// be a good citizen and clean up any running threads
		<-errchan
		imageLogger.WithError(err).Error("Could not write images to backup")
		return err
	} else if err := <-errchan; err != nil {
		imageLogger.WithError(err).Error("Could not export images for backup")
		return err
	}
	tarOut.Close()

	imageLogger.Info("Exported images to backup")

	return nil
}
1280559
func (p *nfsProvisioner) createExport(directory string, rootSquash bool) (string, uint16, error) {
	path := path.Join(p.exportDir, directory)

	block, exportID, err := p.exporter.AddExportBlock(path, rootSquash, p.exportSubnet)
	if err != nil {
		return "", 0, fmt.Errorf("error adding export block for path %s: %v", path, err)
	}

	err = p.exporter.Export(path)
	if err != nil {
		p.exporter.RemoveExportBlock(block, exportID)
		return "", 0, fmt.Errorf("error exporting export block %s: %v", block, err)
	}

	return block, exportID, nil
}
501485
func (s *Block) Export(precision int) string {
	var k string
	if s.BlockDelete {
		return ""
	}
	for _, c := range s.Nodes {
		k += c.Export(precision)
	}
	return k
}