Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pcp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/pcpImporter
/pcp_*.ptar
/vendor
29 changes: 29 additions & 0 deletions pcp/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
GO = go
EXT =

PLAKAR ?= plakar
VERSION ?= v1.0.0

GOOS := $(shell go env GOOS)
GOARCH := $(shell go env GOARCH)
PTAR := pcp_$(VERSION)_$(GOOS)_$(GOARCH).ptar

all: build

build:
${GO} build -v -o pcpImporter${EXT} ./plugin/importer

package: build
rm -f $(PTAR)
$(PLAKAR) pkg create ./manifest.yaml $(VERSION)

uninstall:
-$(PLAKAR) pkg rm pcp

install: package
$(PLAKAR) pkg add ./$(PTAR)

reinstall: uninstall install

clean:
rm -f pcpImporter
50 changes: 50 additions & 0 deletions pcp/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
module github.com/PlakarKorp/integrations/pcp

go 1.26.2

require (
github.com/PlakarKorp/go-kloset-sdk v1.1.0-beta.1
github.com/PlakarKorp/integrations/fs v1.1.0-beta.8
github.com/PlakarKorp/integrations/postgresql v1.1.0-beta.8
github.com/PlakarKorp/kloset v1.1.0-rc.4
)

require (
github.com/PlakarKorp/integration-grpc v1.1.0-beta.3 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.9.0 // indirect
github.com/go-git/go-git/v5 v5.19.1 // indirect
github.com/golang/snappy v1.0.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/pgx/v5 v5.9.1 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/ncruces/go-strftime v1.0.0 // indirect
github.com/nickball/go-aes-key-wrap v0.0.0-20170929221519-1c3aa3e4dfc5 // indirect
github.com/pierrec/lz4/v4 v4.1.26 // indirect
github.com/pkg/xattr v0.4.12 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/tink-crypto/tink-go/v2 v2.6.0 // indirect
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/zeebo/blake3 v0.2.4 // indirect
golang.org/x/crypto v0.52.0 // indirect
golang.org/x/mod v0.36.0 // indirect
golang.org/x/net v0.54.0 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.45.0 // indirect
golang.org/x/text v0.37.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect
google.golang.org/grpc v1.79.2 // indirect
google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
modernc.org/libc v1.72.3 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
modernc.org/sqlite v1.50.1 // indirect
)
209 changes: 209 additions & 0 deletions pcp/go.sum

Large diffs are not rendered by default.

133 changes: 133 additions & 0 deletions pcp/importer/importer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package importer

import (
"context"
"fmt"
"os"
"path"
"path/filepath"
"strings"

fsimporter "github.com/PlakarKorp/integrations/fs/importer"
pgimporter "github.com/PlakarKorp/integrations/postgresql/importer"
"github.com/PlakarKorp/kloset/connectors"
"github.com/PlakarKorp/kloset/connectors/importer"
"github.com/PlakarKorp/kloset/location"
)

func init() {
importer.Register("pcp", location.FLAG_STREAM, NewImporter)
}

type SubImporter struct {
Prefix string
Importer importer.Importer
}

type Importer struct {
opts *connectors.Options
subImporters []SubImporter
}

const APPLIANCE_DATA_DIR = "/appliance_data"

func NewImporter(appCtx context.Context, opts *connectors.Options, name string, config map[string]string) (importer.Importer, error) {
subImporters := []SubImporter{}

rawPassword, err := os.ReadFile(filepath.Join(APPLIANCE_DATA_DIR, "secrets/db_password"))
if err != nil {
return nil, fmt.Errorf("reading db password: %w", err)
}

pgImporter, err := pgimporter.NewImporter(appCtx, opts, "postgres", map[string]string{
"host": "postgres",
"port": "5432",
"username": "plakman",
"password": strings.TrimSpace(string(rawPassword)),
})
if err != nil {
return nil, err
}

subImporters = append(subImporters, SubImporter{
Prefix: "/db",
Importer: pgImporter,
})

for _, name := range []string{"secrets", "ssh", "logs", "plakman", "plakman_runtime/instance.key", "plakman_runtime/license.jwt", "plakman_runtime/pki"} {
path := filepath.Join(APPLIANCE_DATA_DIR, name)

fsImporter, err := fsimporter.NewFSImporter(appCtx, opts, "fs", map[string]string{
"location": "fs://" + path,
})
if err != nil {
return nil, err
}

subImporters = append(subImporters, SubImporter{
Prefix: "/fs",
Importer: fsImporter,
})
}

return &Importer{
opts: opts,
subImporters: subImporters,
}, nil
}

func (p *Importer) Import(ctx context.Context, records chan<- *connectors.Record, results <-chan *connectors.Result) error {
defer close(records)

// Each sub-importer closes its own records channel, so we give each one a
// private subRecords channel and relay into the shared records channel ourselves.
// results is passed through unchanged: none of our sub-importers are
// stream-based, so they never read acks from it.
for _, sub := range p.subImporters {
subRecords := make(chan *connectors.Record)
err := make(chan error, 1)

go func(sub importer.Importer) {
err <- sub.Import(ctx, subRecords, results)
}(sub.Importer)

for rec := range subRecords {
rec.Pathname = path.Join(sub.Prefix, rec.Pathname)
records <- rec
}

if subErr := <-err; subErr != nil {
return subErr
}
}
return nil
}

func (p *Importer) Ping(ctx context.Context) error {
for _, sub := range p.subImporters {
if err := sub.Importer.Ping(ctx); err != nil {
return err
}
}
return nil
}

func (p *Importer) Close(ctx context.Context) error {
for _, sub := range p.subImporters {
if err := sub.Importer.Close(ctx); err != nil {
return err
}
}
return nil
}

func (p *Importer) Root() string { return "/" }
func (p *Importer) Origin() string { return p.opts.Hostname }
func (p *Importer) Type() string { return "pcp" }

// FLAG_STREAM tells the framework not to pre-count records. Without it, the
// framework runs the importer twice to populate the progress bar — which would
// trigger two full PostgreSQL backups.
func (p *Importer) Flags() location.Flags {
return location.FLAG_STREAM
}
7 changes: 7 additions & 0 deletions pcp/importer/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Plakar Control Plane Importer Configuration",
"type": "object",
"additionalProperties": false,
"properties": {}
}
15 changes: 15 additions & 0 deletions pcp/manifest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: pcp
display_name: Plakar Control Plane
description: Back up your instance of Plakar Control Plane.
api_version: v1.1.0
homepage: https://github.com/PlakarKorp/integrations/tree/main/plakar-control-plane
license: ISC
tier: official
contact: mailto:help@plakar.io
connectors:
- type: importer
executable: pcpImporter
homepage: https://github.com/PlakarKorp/integrations/tree/main/plakar-control-plane
license: ISC
protocols: [pcp]
validator: ./importer/schema.json
12 changes: 12 additions & 0 deletions pcp/plugin/importer/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

import (
"os"

sdk "github.com/PlakarKorp/go-kloset-sdk"
"github.com/PlakarKorp/integrations/pcp/importer"
)

func main() {
sdk.EntrypointImporter(os.Args, importer.NewImporter)
}