diff --git a/pkg/clouds/supported.go b/pkg/clouds/supported.go index fdec7b368a..dc9d40ebc8 100644 --- a/pkg/clouds/supported.go +++ b/pkg/clouds/supported.go @@ -50,6 +50,8 @@ func GuessCloudForPath(path string) (kops.CloudProviderID, error) { return kops.CloudProviderAzure, nil case strings.HasPrefix(path, "do://"): return kops.CloudProviderDO, nil + case strings.HasPrefix(path, "hos://"): + return kops.CloudProviderHetzner, nil case strings.HasPrefix(path, "gs://"): return kops.CloudProviderGCE, nil case strings.HasPrefix(path, "scw://"): diff --git a/util/pkg/vfs/context.go b/util/pkg/vfs/context.go index 7cde7aae23..b86f2c7f79 100644 --- a/util/pkg/vfs/context.go +++ b/util/pkg/vfs/context.go @@ -185,6 +185,10 @@ func (c *VFSContext) BuildVfsPath(p string) (Path, error) { return c.buildDOPath(p) } + if strings.HasPrefix(p, "hos://") { + return c.buildHetznerPath(p) + } + if strings.HasPrefix(p, "memfs://") { return c.buildMemFSPath(p) } @@ -356,6 +360,24 @@ func (c *VFSContext) buildDOPath(p string) (*S3Path, error) { return s3path, nil } +func (c *VFSContext) buildHetznerPath(p string) (*S3Path, error) { + u, err := url.Parse(p) + if err != nil { + return nil, fmt.Errorf("invalid Hetzner Object Storage path: %q", p) + } + if u.Scheme != "hos" { + return nil, fmt.Errorf("invalid Hetzner object storage path: %q", p) + } + + bucket := strings.TrimSuffix(u.Host, "/") + if bucket == "" { + return nil, fmt.Errorf("invalid Hetzner object storage path: %q", p) + } + + s3path := newS3Path(c.s3Context, u.Scheme, bucket, u.Path, false) + return s3path, nil +} + func (c *VFSContext) buildKubernetesPath(p string) (*KubernetesPath, error) { u, err := url.Parse(p) if err != nil {