Support running in any namespace
Add the ability for the Ark server to run in any namespace. Add `ark client config get/set` for manipulating the new client configuration file in $HOME/.config/ark/config.json. This holds client defaults, such as the Ark server's namespace (to avoid having to specify the --namespace flag all the time). Add a --namespace flag to all client commands. Signed-off-by: Andy Goldstein <andy.goldstein@gmail.com>pull/272/head
parent
d56b5f2b66
commit
816f14c0b4
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 the Heptio Ark contributors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ConfigKeyNamespace = "namespace"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LoadConfig loads the Ark client configuration file and returns it as a map[string]string. If the
|
||||||
|
// file does not exist, an empty map is returned.
|
||||||
|
func LoadConfig() (map[string]string, error) {
|
||||||
|
fileName := configFileName()
|
||||||
|
|
||||||
|
_, err := os.Stat(fileName)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
// If the file isn't there, just return an empty map
|
||||||
|
return map[string]string{}, nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
// For any other Stat() error, return it
|
||||||
|
return nil, errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
configFile, err := os.Open(fileName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.WithStack(err)
|
||||||
|
}
|
||||||
|
defer configFile.Close()
|
||||||
|
|
||||||
|
var config map[string]string
|
||||||
|
if err := json.NewDecoder(configFile).Decode(&config); err != nil {
|
||||||
|
return nil, errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveConfig saves the passed in config map to the Ark client configuration file.
|
||||||
|
func SaveConfig(config map[string]string) error {
|
||||||
|
fileName := configFileName()
|
||||||
|
|
||||||
|
configFile, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0755)
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
defer configFile.Close()
|
||||||
|
|
||||||
|
return json.NewEncoder(configFile).Encode(&config)
|
||||||
|
}
|
||||||
|
|
||||||
|
func configFileName() string {
|
||||||
|
return filepath.Join(os.Getenv("HOME"), ".config", "ark", "config.json")
|
||||||
|
}
|
|
@ -17,30 +17,36 @@ limitations under the License.
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
|
|
||||||
|
"github.com/heptio/ark/pkg/apis/ark/v1"
|
||||||
clientset "github.com/heptio/ark/pkg/generated/clientset/versioned"
|
clientset "github.com/heptio/ark/pkg/generated/clientset/versioned"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Factory knows how to create an ArkClient and Kubernetes client.
|
// Factory knows how to create an ArkClient and Kubernetes client.
|
||||||
type Factory interface {
|
type Factory interface {
|
||||||
// BindFlags binds common flags such as --kubeconfig to the passed-in FlagSet.
|
// BindFlags binds common flags (--kubeconfig, --namespace) to the passed-in FlagSet.
|
||||||
BindFlags(flags *pflag.FlagSet)
|
BindFlags(flags *pflag.FlagSet)
|
||||||
// Client returns an ArkClient. It uses the following priority to specify the cluster
|
// Client returns an ArkClient. It uses the following priority to specify the cluster
|
||||||
// configuration: --kubeconfig flag, KUBECONFIG environment variable, in-cluster configuration.
|
// configuration: --kubeconfig flag, KUBECONFIG environment variable, in-cluster configuration.
|
||||||
Client() (clientset.Interface, error)
|
Client() (clientset.Interface, error)
|
||||||
// KubeClient returns a Kubernetes client. It uses the following priority to specify the cluster
|
// KubeClient returns a Kubernetes client. It uses the following priority to specify the cluster
|
||||||
// configuration: --kubeconfig flag, KUBECONFIG environment variable, in-cluster configuration.
|
// configuration: --kubeconfig flag, KUBECONFIG environment variable, in-cluster configuration.
|
||||||
KubeClient() (kubernetes.Interface, error)
|
KubeClient() (kubernetes.Interface, error)
|
||||||
|
Namespace() string
|
||||||
}
|
}
|
||||||
|
|
||||||
type factory struct {
|
type factory struct {
|
||||||
flags *pflag.FlagSet
|
flags *pflag.FlagSet
|
||||||
kubeconfig string
|
kubeconfig string
|
||||||
baseName string
|
baseName string
|
||||||
|
namespace string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFactory returns a Factory.
|
// NewFactory returns a Factory.
|
||||||
|
@ -49,7 +55,19 @@ func NewFactory(baseName string) Factory {
|
||||||
flags: pflag.NewFlagSet("", pflag.ContinueOnError),
|
flags: pflag.NewFlagSet("", pflag.ContinueOnError),
|
||||||
baseName: baseName,
|
baseName: baseName,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config, err := LoadConfig(); err == nil {
|
||||||
|
f.namespace = config[ConfigKeyNamespace]
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(os.Stderr, "WARNING: error retrieving namespace from config file: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.namespace == "" {
|
||||||
|
f.namespace = v1.DefaultNamespace
|
||||||
|
}
|
||||||
|
|
||||||
f.flags.StringVar(&f.kubeconfig, "kubeconfig", "", "Path to the kubeconfig file to use to talk to the Kubernetes apiserver. If unset, try the environment variable KUBECONFIG, as well as in-cluster configuration")
|
f.flags.StringVar(&f.kubeconfig, "kubeconfig", "", "Path to the kubeconfig file to use to talk to the Kubernetes apiserver. If unset, try the environment variable KUBECONFIG, as well as in-cluster configuration")
|
||||||
|
f.flags.StringVarP(&f.namespace, "namespace", "n", f.namespace, "The namespace in which Ark should operate")
|
||||||
|
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
@ -83,3 +101,7 @@ func (f *factory) KubeClient() (kubernetes.Interface, error) {
|
||||||
}
|
}
|
||||||
return kubeClient, nil
|
return kubeClient, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *factory) Namespace() string {
|
||||||
|
return f.namespace
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
|
|
||||||
"github.com/heptio/ark/pkg/client"
|
"github.com/heptio/ark/pkg/client"
|
||||||
"github.com/heptio/ark/pkg/cmd/cli/backup"
|
"github.com/heptio/ark/pkg/cmd/cli/backup"
|
||||||
|
cliclient "github.com/heptio/ark/pkg/cmd/cli/client"
|
||||||
"github.com/heptio/ark/pkg/cmd/cli/create"
|
"github.com/heptio/ark/pkg/cmd/cli/create"
|
||||||
"github.com/heptio/ark/pkg/cmd/cli/delete"
|
"github.com/heptio/ark/pkg/cmd/cli/delete"
|
||||||
"github.com/heptio/ark/pkg/cmd/cli/describe"
|
"github.com/heptio/ark/pkg/cmd/cli/describe"
|
||||||
|
@ -63,6 +64,7 @@ operations can also be performed as 'ark backup get' and 'ark schedule create'.`
|
||||||
runplugin.NewCommand(),
|
runplugin.NewCommand(),
|
||||||
plugin.NewCommand(f),
|
plugin.NewCommand(f),
|
||||||
delete.NewCommand(f),
|
delete.NewCommand(f),
|
||||||
|
cliclient.NewCommand(),
|
||||||
)
|
)
|
||||||
|
|
||||||
// add the glog flags
|
// add the glog flags
|
||||||
|
|
|
@ -118,7 +118,7 @@ func (o *CreateOptions) Run(c *cobra.Command, f client.Factory) error {
|
||||||
|
|
||||||
backup := &api.Backup{
|
backup := &api.Backup{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Namespace: api.DefaultNamespace,
|
Namespace: f.Namespace(),
|
||||||
Name: o.Name,
|
Name: o.Name,
|
||||||
Labels: o.Labels.Data(),
|
Labels: o.Labels.Data(),
|
||||||
},
|
},
|
||||||
|
|
|
@ -23,7 +23,6 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
api "github.com/heptio/ark/pkg/apis/ark/v1"
|
|
||||||
"github.com/heptio/ark/pkg/client"
|
"github.com/heptio/ark/pkg/client"
|
||||||
"github.com/heptio/ark/pkg/cmd"
|
"github.com/heptio/ark/pkg/cmd"
|
||||||
"github.com/heptio/ark/pkg/controller"
|
"github.com/heptio/ark/pkg/controller"
|
||||||
|
@ -55,7 +54,7 @@ func NewDeleteCommand(f client.Factory, use string) *cobra.Command {
|
||||||
|
|
||||||
backupName := args[0]
|
backupName := args[0]
|
||||||
|
|
||||||
err = arkClient.ArkV1().Backups(api.DefaultNamespace).Delete(backupName, nil)
|
err = arkClient.ArkV1().Backups(f.Namespace()).Delete(backupName, nil)
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
|
|
||||||
fmt.Printf("Backup %q deleted\n", backupName)
|
fmt.Printf("Backup %q deleted\n", backupName)
|
||||||
|
|
|
@ -42,12 +42,12 @@ func NewDescribeCommand(f client.Factory, use string) *cobra.Command {
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
backups = new(v1.BackupList)
|
backups = new(v1.BackupList)
|
||||||
for _, name := range args {
|
for _, name := range args {
|
||||||
backup, err := arkClient.Ark().Backups(v1.DefaultNamespace).Get(name, metav1.GetOptions{})
|
backup, err := arkClient.Ark().Backups(f.Namespace()).Get(name, metav1.GetOptions{})
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
backups.Items = append(backups.Items, *backup)
|
backups.Items = append(backups.Items, *backup)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
backups, err = arkClient.ArkV1().Backups(v1.DefaultNamespace).List(listOptions)
|
backups, err = arkClient.ArkV1().Backups(f.Namespace()).List(listOptions)
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,7 @@ func (o *DownloadOptions) Run(c *cobra.Command, f client.Factory) error {
|
||||||
}
|
}
|
||||||
defer backupDest.Close()
|
defer backupDest.Close()
|
||||||
|
|
||||||
err = downloadrequest.Stream(arkClient.ArkV1(), o.Name, v1.DownloadTargetKindBackupContents, backupDest, o.Timeout)
|
err = downloadrequest.Stream(arkClient.ArkV1(), f.Namespace(), o.Name, v1.DownloadTargetKindBackupContents, backupDest, o.Timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Remove(o.Output)
|
os.Remove(o.Output)
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
|
|
|
@ -44,12 +44,12 @@ func NewGetCommand(f client.Factory, use string) *cobra.Command {
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
backups = new(api.BackupList)
|
backups = new(api.BackupList)
|
||||||
for _, name := range args {
|
for _, name := range args {
|
||||||
backup, err := arkClient.Ark().Backups(api.DefaultNamespace).Get(name, metav1.GetOptions{})
|
backup, err := arkClient.Ark().Backups(f.Namespace()).Get(name, metav1.GetOptions{})
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
backups.Items = append(backups.Items, *backup)
|
backups.Items = append(backups.Items, *backup)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
backups, err = arkClient.ArkV1().Backups(api.DefaultNamespace).List(listOptions)
|
backups, err = arkClient.ArkV1().Backups(f.Namespace()).List(listOptions)
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ func NewLogsCommand(f client.Factory) *cobra.Command {
|
||||||
arkClient, err := f.Client()
|
arkClient, err := f.Client()
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
|
|
||||||
err = downloadrequest.Stream(arkClient.ArkV1(), args[0], v1.DownloadTargetKindBackupLog, os.Stdout, timeout)
|
err = downloadrequest.Stream(arkClient.ArkV1(), f.Namespace(), args[0], v1.DownloadTargetKindBackupLog, os.Stdout, timeout)
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2017 the Heptio Ark contributors.
|
Copyright 2018 the Heptio Ark contributors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,16 +14,22 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package config
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/heptio/ark/pkg/cmd/cli/client/config"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/heptio/ark/pkg/client"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewGetCommand(f client.Factory) *cobra.Command {
|
func NewCommand() *cobra.Command {
|
||||||
c := &cobra.Command{}
|
c := &cobra.Command{
|
||||||
|
Use: "client",
|
||||||
|
Short: "Ark client related commands",
|
||||||
|
}
|
||||||
|
|
||||||
|
c.AddCommand(
|
||||||
|
config.NewCommand(),
|
||||||
|
)
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
|
@ -18,20 +18,17 @@ package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/heptio/ark/pkg/client"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewCommand(f client.Factory) *cobra.Command {
|
func NewCommand() *cobra.Command {
|
||||||
c := &cobra.Command{
|
c := &cobra.Command{
|
||||||
Use: "config",
|
Use: "config",
|
||||||
Short: "Work with config",
|
Short: "Get and set client configuration file values",
|
||||||
Long: "Work with config",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.AddCommand(
|
c.AddCommand(
|
||||||
NewGetCommand(f),
|
NewGetCommand(),
|
||||||
NewSetCommand(f),
|
NewSetCommand(),
|
||||||
)
|
)
|
||||||
|
|
||||||
return c
|
return c
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 the Heptio Ark contributors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/heptio/ark/pkg/client"
|
||||||
|
"github.com/heptio/ark/pkg/cmd"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewGetCommand() *cobra.Command {
|
||||||
|
c := &cobra.Command{
|
||||||
|
Use: "get [KEY 1] [KEY 2] [...]",
|
||||||
|
Short: "Get client configuration file values",
|
||||||
|
Run: func(c *cobra.Command, args []string) {
|
||||||
|
config, err := client.LoadConfig()
|
||||||
|
cmd.CheckError(err)
|
||||||
|
|
||||||
|
if len(args) == 0 {
|
||||||
|
keys := make([]string, 0, len(config))
|
||||||
|
for key := range config {
|
||||||
|
keys = append(keys, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(keys)
|
||||||
|
|
||||||
|
for _, key := range keys {
|
||||||
|
fmt.Printf("%s: %s\n", key, config[key])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, key := range args {
|
||||||
|
value, found := config[key]
|
||||||
|
if !found {
|
||||||
|
value = "<NOT SET>"
|
||||||
|
}
|
||||||
|
fmt.Printf("%s: %s\n", key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 the Heptio Ark contributors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/heptio/ark/pkg/client"
|
||||||
|
"github.com/heptio/ark/pkg/cmd"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewSetCommand() *cobra.Command {
|
||||||
|
c := &cobra.Command{
|
||||||
|
Use: "set KEY=VALUE [KEY=VALUE]...",
|
||||||
|
Short: "Set client configuration file values",
|
||||||
|
Run: func(c *cobra.Command, args []string) {
|
||||||
|
if len(args) < 1 {
|
||||||
|
cmd.CheckError(errors.Errorf("At least one KEY=VALUE argument is required"))
|
||||||
|
}
|
||||||
|
|
||||||
|
config, err := client.LoadConfig()
|
||||||
|
cmd.CheckError(err)
|
||||||
|
|
||||||
|
for _, arg := range args {
|
||||||
|
pair := strings.Split(arg, "=")
|
||||||
|
if len(pair) != 2 {
|
||||||
|
fmt.Fprintf(os.Stderr, "WARNING: invalid KEY=VALUE: %q\n", arg)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
key, value := pair[0], pair[1]
|
||||||
|
|
||||||
|
if value == "" {
|
||||||
|
delete(config, key)
|
||||||
|
} else {
|
||||||
|
config[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.CheckError(client.SaveConfig(config))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2017 the Heptio Ark contributors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
|
|
||||||
"github.com/heptio/ark/pkg/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewSetCommand(f client.Factory) *cobra.Command {
|
|
||||||
c := &cobra.Command{}
|
|
||||||
|
|
||||||
return c
|
|
||||||
}
|
|
|
@ -30,7 +30,6 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
||||||
|
|
||||||
ark "github.com/heptio/ark/pkg/apis/ark/v1"
|
|
||||||
"github.com/heptio/ark/pkg/client"
|
"github.com/heptio/ark/pkg/client"
|
||||||
"github.com/heptio/ark/pkg/cmd"
|
"github.com/heptio/ark/pkg/cmd"
|
||||||
"github.com/heptio/ark/pkg/cmd/util/flag"
|
"github.com/heptio/ark/pkg/cmd/util/flag"
|
||||||
|
@ -61,7 +60,7 @@ func NewAddCommand(f client.Factory) *cobra.Command {
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
arkDeploy, err := kubeClient.AppsV1beta1().Deployments(ark.DefaultNamespace).Get(arkDeployment, metav1.GetOptions{})
|
arkDeploy, err := kubeClient.AppsV1beta1().Deployments(f.Namespace()).Get(arkDeployment, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
}
|
}
|
||||||
|
@ -131,7 +130,7 @@ func NewAddCommand(f client.Factory) *cobra.Command {
|
||||||
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(original, updated, v1beta1.Deployment{})
|
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(original, updated, v1beta1.Deployment{})
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
|
|
||||||
_, err = kubeClient.AppsV1beta1().Deployments(ark.DefaultNamespace).Patch(arkDeploy.Name, types.StrategicMergePatchType, patchBytes)
|
_, err = kubeClient.AppsV1beta1().Deployments(arkDeploy.Namespace).Patch(arkDeploy.Name, types.StrategicMergePatchType, patchBytes)
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
||||||
|
|
||||||
ark "github.com/heptio/ark/pkg/apis/ark/v1"
|
|
||||||
"github.com/heptio/ark/pkg/client"
|
"github.com/heptio/ark/pkg/client"
|
||||||
"github.com/heptio/ark/pkg/cmd"
|
"github.com/heptio/ark/pkg/cmd"
|
||||||
)
|
)
|
||||||
|
@ -46,7 +45,7 @@ func NewRemoveCommand(f client.Factory) *cobra.Command {
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
arkDeploy, err := kubeClient.AppsV1beta1().Deployments(ark.DefaultNamespace).Get(arkDeployment, metav1.GetOptions{})
|
arkDeploy, err := kubeClient.AppsV1beta1().Deployments(f.Namespace()).Get(arkDeployment, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
}
|
}
|
||||||
|
@ -78,7 +77,7 @@ func NewRemoveCommand(f client.Factory) *cobra.Command {
|
||||||
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(original, updated, v1beta1.Deployment{})
|
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(original, updated, v1beta1.Deployment{})
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
|
|
||||||
_, err = kubeClient.AppsV1beta1().Deployments(ark.DefaultNamespace).Patch(arkDeploy.Name, types.StrategicMergePatchType, patchBytes)
|
_, err = kubeClient.AppsV1beta1().Deployments(arkDeploy.Namespace).Patch(arkDeploy.Name, types.StrategicMergePatchType, patchBytes)
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ func (o *CreateOptions) Run(c *cobra.Command, f client.Factory) error {
|
||||||
|
|
||||||
restore := &api.Restore{
|
restore := &api.Restore{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Namespace: api.DefaultNamespace,
|
Namespace: f.Namespace(),
|
||||||
Name: fmt.Sprintf("%s-%s", o.BackupName, time.Now().Format("20060102150405")),
|
Name: fmt.Sprintf("%s-%s", o.BackupName, time.Now().Format("20060102150405")),
|
||||||
Labels: o.Labels.Data(),
|
Labels: o.Labels.Data(),
|
||||||
},
|
},
|
||||||
|
|
|
@ -22,7 +22,6 @@ import (
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
api "github.com/heptio/ark/pkg/apis/ark/v1"
|
|
||||||
"github.com/heptio/ark/pkg/client"
|
"github.com/heptio/ark/pkg/client"
|
||||||
"github.com/heptio/ark/pkg/cmd"
|
"github.com/heptio/ark/pkg/cmd"
|
||||||
)
|
)
|
||||||
|
@ -42,7 +41,7 @@ func NewDeleteCommand(f client.Factory, use string) *cobra.Command {
|
||||||
|
|
||||||
name := args[0]
|
name := args[0]
|
||||||
|
|
||||||
err = arkClient.ArkV1().Restores(api.DefaultNamespace).Delete(name, nil)
|
err = arkClient.ArkV1().Restores(f.Namespace()).Delete(name, nil)
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
|
|
||||||
fmt.Printf("Restore %q deleted\n", name)
|
fmt.Printf("Restore %q deleted\n", name)
|
||||||
|
|
|
@ -42,12 +42,12 @@ func NewDescribeCommand(f client.Factory, use string) *cobra.Command {
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
restores = new(api.RestoreList)
|
restores = new(api.RestoreList)
|
||||||
for _, name := range args {
|
for _, name := range args {
|
||||||
restore, err := arkClient.Ark().Restores(api.DefaultNamespace).Get(name, metav1.GetOptions{})
|
restore, err := arkClient.Ark().Restores(f.Namespace()).Get(name, metav1.GetOptions{})
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
restores.Items = append(restores.Items, *restore)
|
restores.Items = append(restores.Items, *restore)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
restores, err = arkClient.ArkV1().Restores(api.DefaultNamespace).List(listOptions)
|
restores, err = arkClient.ArkV1().Restores(f.Namespace()).List(listOptions)
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,12 +44,12 @@ func NewGetCommand(f client.Factory, use string) *cobra.Command {
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
restores = new(api.RestoreList)
|
restores = new(api.RestoreList)
|
||||||
for _, name := range args {
|
for _, name := range args {
|
||||||
restore, err := arkClient.Ark().Restores(api.DefaultNamespace).Get(name, metav1.GetOptions{})
|
restore, err := arkClient.Ark().Restores(f.Namespace()).Get(name, metav1.GetOptions{})
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
restores.Items = append(restores.Items, *restore)
|
restores.Items = append(restores.Items, *restore)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
restores, err = arkClient.ArkV1().Restores(api.DefaultNamespace).List(listOptions)
|
restores, err = arkClient.ArkV1().Restores(f.Namespace()).List(listOptions)
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ func NewLogsCommand(f client.Factory) *cobra.Command {
|
||||||
arkClient, err := f.Client()
|
arkClient, err := f.Client()
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
|
|
||||||
err = downloadrequest.Stream(arkClient.ArkV1(), args[0], v1.DownloadTargetKindRestoreLog, os.Stdout, timeout)
|
err = downloadrequest.Stream(arkClient.ArkV1(), f.Namespace(), args[0], v1.DownloadTargetKindRestoreLog, os.Stdout, timeout)
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ func (o *CreateOptions) Run(c *cobra.Command, f client.Factory) error {
|
||||||
|
|
||||||
schedule := &api.Schedule{
|
schedule := &api.Schedule{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Namespace: api.DefaultNamespace,
|
Namespace: f.Namespace(),
|
||||||
Name: o.BackupOptions.Name,
|
Name: o.BackupOptions.Name,
|
||||||
},
|
},
|
||||||
Spec: api.ScheduleSpec{
|
Spec: api.ScheduleSpec{
|
||||||
|
|
|
@ -22,7 +22,6 @@ import (
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
api "github.com/heptio/ark/pkg/apis/ark/v1"
|
|
||||||
"github.com/heptio/ark/pkg/client"
|
"github.com/heptio/ark/pkg/client"
|
||||||
"github.com/heptio/ark/pkg/cmd"
|
"github.com/heptio/ark/pkg/cmd"
|
||||||
)
|
)
|
||||||
|
@ -42,7 +41,7 @@ func NewDeleteCommand(f client.Factory, use string) *cobra.Command {
|
||||||
|
|
||||||
name := args[0]
|
name := args[0]
|
||||||
|
|
||||||
err = arkClient.ArkV1().Schedules(api.DefaultNamespace).Delete(name, nil)
|
err = arkClient.ArkV1().Schedules(f.Namespace()).Delete(name, nil)
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
|
|
||||||
fmt.Printf("Schedule %q deleted\n", name)
|
fmt.Printf("Schedule %q deleted\n", name)
|
||||||
|
|
|
@ -42,12 +42,12 @@ func NewDescribeCommand(f client.Factory, use string) *cobra.Command {
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
schedules = new(v1.ScheduleList)
|
schedules = new(v1.ScheduleList)
|
||||||
for _, name := range args {
|
for _, name := range args {
|
||||||
schedule, err := arkClient.Ark().Schedules(v1.DefaultNamespace).Get(name, metav1.GetOptions{})
|
schedule, err := arkClient.Ark().Schedules(f.Namespace()).Get(name, metav1.GetOptions{})
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
schedules.Items = append(schedules.Items, *schedule)
|
schedules.Items = append(schedules.Items, *schedule)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
schedules, err = arkClient.ArkV1().Schedules(v1.DefaultNamespace).List(listOptions)
|
schedules, err = arkClient.ArkV1().Schedules(f.Namespace()).List(listOptions)
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,12 +44,12 @@ func NewGetCommand(f client.Factory, use string) *cobra.Command {
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
schedules = new(api.ScheduleList)
|
schedules = new(api.ScheduleList)
|
||||||
for _, name := range args {
|
for _, name := range args {
|
||||||
schedule, err := arkClient.Ark().Schedules(api.DefaultNamespace).Get(name, metav1.GetOptions{})
|
schedule, err := arkClient.Ark().Schedules(f.Namespace()).Get(name, metav1.GetOptions{})
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
schedules.Items = append(schedules.Items, *schedule)
|
schedules.Items = append(schedules.Items, *schedule)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
schedules, err = arkClient.ArkV1().Schedules(api.DefaultNamespace).List(listOptions)
|
schedules, err = arkClient.ArkV1().Schedules(f.Namespace()).List(listOptions)
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ package server
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -29,6 +30,7 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
@ -61,7 +63,6 @@ import (
|
||||||
|
|
||||||
func NewCommand() *cobra.Command {
|
func NewCommand() *cobra.Command {
|
||||||
var (
|
var (
|
||||||
kubeconfig string
|
|
||||||
sortedLogLevels = getSortedLogLevels()
|
sortedLogLevels = getSortedLogLevels()
|
||||||
logLevelFlag = flag.NewEnum(logrus.InfoLevel.String(), sortedLogLevels...)
|
logLevelFlag = flag.NewEnum(logrus.InfoLevel.String(), sortedLogLevels...)
|
||||||
)
|
)
|
||||||
|
@ -86,7 +87,21 @@ func NewCommand() *cobra.Command {
|
||||||
logger := newLogger(logLevel, &logging.ErrorLocationHook{}, &logging.LogLocationHook{})
|
logger := newLogger(logLevel, &logging.ErrorLocationHook{}, &logging.LogLocationHook{})
|
||||||
logger.Infof("Starting Ark server %s", buildinfo.FormattedGitSHA())
|
logger.Infof("Starting Ark server %s", buildinfo.FormattedGitSHA())
|
||||||
|
|
||||||
s, err := newServer(kubeconfig, fmt.Sprintf("%s-%s", c.Parent().Name(), c.Name()), logger)
|
// NOTE: the namespace flag is bound to ark's persistent flags when the root ark command
|
||||||
|
// creates the client Factory and binds the Factory's flags. We're not using a Factory here in
|
||||||
|
// the server because the Factory gets its basename set at creation time, and the basename is
|
||||||
|
// used to construct the user-agent for clients. Also, the Factory's Namespace() method uses
|
||||||
|
// the client config file to determine the appropriate namespace to use, and that isn't
|
||||||
|
// applicable to the server (it uses the method directly below instead). We could potentially
|
||||||
|
// add a SetBasename() method to the Factory, and tweak how Namespace() works, if we wanted to
|
||||||
|
// have the server use the Factory.
|
||||||
|
namespaceFlag := c.Flag("namespace")
|
||||||
|
if namespaceFlag == nil {
|
||||||
|
cmd.CheckError(errors.New("unable to look up namespace flag"))
|
||||||
|
}
|
||||||
|
namespace := getServerNamespace(namespaceFlag)
|
||||||
|
|
||||||
|
s, err := newServer(namespace, fmt.Sprintf("%s-%s", c.Parent().Name(), c.Name()), logger)
|
||||||
|
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
|
|
||||||
|
@ -95,11 +110,24 @@ func NewCommand() *cobra.Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
command.Flags().Var(logLevelFlag, "log-level", fmt.Sprintf("the level at which to log. Valid values are %s.", strings.Join(sortedLogLevels, ", ")))
|
command.Flags().Var(logLevelFlag, "log-level", fmt.Sprintf("the level at which to log. Valid values are %s.", strings.Join(sortedLogLevels, ", ")))
|
||||||
command.Flags().StringVar(&kubeconfig, "kubeconfig", "", "Path to the kubeconfig file to use to talk to the Kubernetes apiserver. If unset, try the environment variable KUBECONFIG, as well as in-cluster configuration")
|
|
||||||
|
|
||||||
return command
|
return command
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getServerNamespace(namespaceFlag *pflag.Flag) string {
|
||||||
|
if namespaceFlag.Changed {
|
||||||
|
return namespaceFlag.Value.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if data, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"); err == nil {
|
||||||
|
if ns := strings.TrimSpace(string(data)); len(ns) > 0 {
|
||||||
|
return ns
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return api.DefaultNamespace
|
||||||
|
}
|
||||||
|
|
||||||
func newLogger(level logrus.Level, hooks ...logrus.Hook) *logrus.Logger {
|
func newLogger(level logrus.Level, hooks ...logrus.Hook) *logrus.Logger {
|
||||||
logger := logrus.New()
|
logger := logrus.New()
|
||||||
logger.Level = level
|
logger.Level = level
|
||||||
|
@ -132,6 +160,7 @@ func getSortedLogLevels() []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
type server struct {
|
type server struct {
|
||||||
|
namespace string
|
||||||
kubeClientConfig *rest.Config
|
kubeClientConfig *rest.Config
|
||||||
kubeClient kubernetes.Interface
|
kubeClient kubernetes.Interface
|
||||||
arkClient clientset.Interface
|
arkClient clientset.Interface
|
||||||
|
@ -146,8 +175,8 @@ type server struct {
|
||||||
pluginManager plugin.Manager
|
pluginManager plugin.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
func newServer(kubeconfig, baseName string, logger *logrus.Logger) (*server, error) {
|
func newServer(namespace, baseName string, logger *logrus.Logger) (*server, error) {
|
||||||
clientConfig, err := client.Config(kubeconfig, baseName)
|
clientConfig, err := client.Config("", baseName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -170,12 +199,13 @@ func newServer(kubeconfig, baseName string, logger *logrus.Logger) (*server, err
|
||||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||||
|
|
||||||
s := &server{
|
s := &server{
|
||||||
|
namespace: namespace,
|
||||||
kubeClientConfig: clientConfig,
|
kubeClientConfig: clientConfig,
|
||||||
kubeClient: kubeClient,
|
kubeClient: kubeClient,
|
||||||
arkClient: arkClient,
|
arkClient: arkClient,
|
||||||
discoveryClient: arkClient.Discovery(),
|
discoveryClient: arkClient.Discovery(),
|
||||||
clientPool: dynamic.NewDynamicClientPool(clientConfig),
|
clientPool: dynamic.NewDynamicClientPool(clientConfig),
|
||||||
sharedInformerFactory: informers.NewSharedInformerFactory(arkClient, 0),
|
sharedInformerFactory: informers.NewFilteredSharedInformerFactory(arkClient, 0, namespace, nil),
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancelFunc: cancelFunc,
|
cancelFunc: cancelFunc,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
|
@ -218,12 +248,12 @@ func (s *server) run() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) ensureArkNamespace() error {
|
func (s *server) ensureArkNamespace() error {
|
||||||
logContext := s.logger.WithField("namespace", api.DefaultNamespace)
|
logContext := s.logger.WithField("namespace", s.namespace)
|
||||||
|
|
||||||
logContext.Info("Ensuring namespace exists for backups")
|
logContext.Info("Ensuring namespace exists for backups")
|
||||||
defaultNamespace := v1.Namespace{
|
defaultNamespace := v1.Namespace{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: api.DefaultNamespace,
|
Name: s.namespace,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +273,7 @@ func (s *server) loadConfig() (*api.Config, error) {
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
for {
|
for {
|
||||||
config, err = s.arkClient.ArkV1().Configs(api.DefaultNamespace).Get("default", metav1.GetOptions{})
|
config, err = s.arkClient.ArkV1().Configs(s.namespace).Get("default", metav1.GetOptions{})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -459,6 +489,7 @@ func (s *server) runControllers(config *api.Config) error {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
scheduleController := controller.NewScheduleController(
|
scheduleController := controller.NewScheduleController(
|
||||||
|
s.namespace,
|
||||||
s.arkClient.ArkV1(),
|
s.arkClient.ArkV1(),
|
||||||
s.arkClient.ArkV1(),
|
s.arkClient.ArkV1(),
|
||||||
s.sharedInformerFactory.Ark().V1().Schedules(),
|
s.sharedInformerFactory.Ark().V1().Schedules(),
|
||||||
|
@ -511,6 +542,7 @@ func (s *server) runControllers(config *api.Config) error {
|
||||||
cmd.CheckError(err)
|
cmd.CheckError(err)
|
||||||
|
|
||||||
restoreController := controller.NewRestoreController(
|
restoreController := controller.NewRestoreController(
|
||||||
|
s.namespace,
|
||||||
s.sharedInformerFactory.Ark().V1().Restores(),
|
s.sharedInformerFactory.Ark().V1().Restores(),
|
||||||
s.arkClient.ArkV1(),
|
s.arkClient.ArkV1(),
|
||||||
s.arkClient.ArkV1(),
|
s.arkClient.ArkV1(),
|
||||||
|
|
|
@ -33,10 +33,10 @@ import (
|
||||||
arkclientv1 "github.com/heptio/ark/pkg/generated/clientset/versioned/typed/ark/v1"
|
arkclientv1 "github.com/heptio/ark/pkg/generated/clientset/versioned/typed/ark/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Stream(client arkclientv1.DownloadRequestsGetter, name string, kind v1.DownloadTargetKind, w io.Writer, timeout time.Duration) error {
|
func Stream(client arkclientv1.DownloadRequestsGetter, namespace, name string, kind v1.DownloadTargetKind, w io.Writer, timeout time.Duration) error {
|
||||||
req := &v1.DownloadRequest{
|
req := &v1.DownloadRequest{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Namespace: v1.DefaultNamespace,
|
Namespace: namespace,
|
||||||
Name: fmt.Sprintf("%s-%s", name, time.Now().Format("20060102150405")),
|
Name: fmt.Sprintf("%s-%s", name, time.Now().Format("20060102150405")),
|
||||||
},
|
},
|
||||||
Spec: v1.DownloadRequestSpec{
|
Spec: v1.DownloadRequestSpec{
|
||||||
|
@ -47,18 +47,19 @@ func Stream(client arkclientv1.DownloadRequestsGetter, name string, kind v1.Down
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := client.DownloadRequests(v1.DefaultNamespace).Create(req)
|
req, err := client.DownloadRequests(namespace).Create(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
defer client.DownloadRequests(v1.DefaultNamespace).Delete(req.Name, nil)
|
defer client.DownloadRequests(namespace).Delete(req.Name, nil)
|
||||||
|
|
||||||
listOptions := metav1.ListOptions{
|
listOptions := metav1.ListOptions{
|
||||||
//TODO: once kube-apiserver http://issue.k8s.io/51046 is fixed, uncomment
|
// TODO: once the minimum supported Kubernetes version is v1.9.0, uncomment the following line.
|
||||||
|
// See http://issue.k8s.io/51046 for details.
|
||||||
//FieldSelector: "metadata.name=" + req.Name
|
//FieldSelector: "metadata.name=" + req.Name
|
||||||
ResourceVersion: req.ResourceVersion,
|
ResourceVersion: req.ResourceVersion,
|
||||||
}
|
}
|
||||||
watcher, err := client.DownloadRequests(v1.DefaultNamespace).Watch(listOptions)
|
watcher, err := client.DownloadRequests(namespace).Watch(listOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
@ -78,6 +79,8 @@ Loop:
|
||||||
return errors.Errorf("unexpected type %T", e.Object)
|
return errors.Errorf("unexpected type %T", e.Object)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: once the minimum supported Kubernetes version is v1.9.0, remove the following check.
|
||||||
|
// See http://issue.k8s.io/51046 for details.
|
||||||
if updated.Name != req.Name {
|
if updated.Name != req.Name {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,7 +150,7 @@ func TestStream(t *testing.T) {
|
||||||
output := new(bytes.Buffer)
|
output := new(bytes.Buffer)
|
||||||
errCh := make(chan error)
|
errCh := make(chan error)
|
||||||
go func() {
|
go func() {
|
||||||
err := Stream(client.ArkV1(), "name", test.kind, output, timeout)
|
err := Stream(client.ArkV1(), "namespace", "name", test.kind, output, timeout)
|
||||||
errCh <- err
|
errCh <- err
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ func describeRestoreResults(d *Describer, restore *v1.Restore, arkClient clients
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
var resultMap map[string]v1.RestoreResult
|
var resultMap map[string]v1.RestoreResult
|
||||||
|
|
||||||
if err := downloadrequest.Stream(arkClient.ArkV1(), restore.Name, v1.DownloadTargetKindRestoreResults, &buf, 30*time.Second); err != nil {
|
if err := downloadrequest.Stream(arkClient.ArkV1(), restore.Namespace, restore.Name, v1.DownloadTargetKindRestoreResults, &buf, 30*time.Second); err != nil {
|
||||||
d.Printf("Warnings:\t<error getting warnings: %v>\n\nErrors:\t<error getting errors: %v>\n", err, err)
|
d.Printf("Warnings:\t<error getting warnings: %v>\n\nErrors:\t<error getting errors: %v>\n", err, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -297,7 +297,7 @@ func patchBackup(original, updated *api.Backup, client arkv1client.BackupsGetter
|
||||||
return nil, errors.Wrap(err, "error creating two-way merge patch for backup")
|
return nil, errors.Wrap(err, "error creating two-way merge patch for backup")
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := client.Backups(api.DefaultNamespace).Patch(original.Name, types.MergePatchType, patchBytes)
|
res, err := client.Backups(original.Namespace).Patch(original.Name, types.MergePatchType, patchBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error patching backup")
|
return nil, errors.Wrap(err, "error patching backup")
|
||||||
}
|
}
|
||||||
|
|
|
@ -276,7 +276,7 @@ func patchDownloadRequest(original, updated *v1.DownloadRequest, client arkv1cli
|
||||||
return nil, errors.Wrap(err, "error creating two-way merge patch for download request")
|
return nil, errors.Wrap(err, "error creating two-way merge patch for download request")
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := client.DownloadRequests(v1.DefaultNamespace).Patch(original.Name, types.MergePatchType, patchBytes)
|
res, err := client.DownloadRequests(original.Namespace).Patch(original.Name, types.MergePatchType, patchBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error patching download request")
|
return nil, errors.Wrap(err, "error patching download request")
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ import (
|
||||||
var nonRestorableResources = []string{"nodes"}
|
var nonRestorableResources = []string{"nodes"}
|
||||||
|
|
||||||
type restoreController struct {
|
type restoreController struct {
|
||||||
|
namespace string
|
||||||
restoreClient arkv1client.RestoresGetter
|
restoreClient arkv1client.RestoresGetter
|
||||||
backupClient arkv1client.BackupsGetter
|
backupClient arkv1client.BackupsGetter
|
||||||
restorer restore.Restorer
|
restorer restore.Restorer
|
||||||
|
@ -71,6 +72,7 @@ type restoreController struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRestoreController(
|
func NewRestoreController(
|
||||||
|
namespace string,
|
||||||
restoreInformer informers.RestoreInformer,
|
restoreInformer informers.RestoreInformer,
|
||||||
restoreClient arkv1client.RestoresGetter,
|
restoreClient arkv1client.RestoresGetter,
|
||||||
backupClient arkv1client.BackupsGetter,
|
backupClient arkv1client.BackupsGetter,
|
||||||
|
@ -83,6 +85,7 @@ func NewRestoreController(
|
||||||
pluginManager plugin.Manager,
|
pluginManager plugin.Manager,
|
||||||
) Interface {
|
) Interface {
|
||||||
c := &restoreController{
|
c := &restoreController{
|
||||||
|
namespace: namespace,
|
||||||
restoreClient: restoreClient,
|
restoreClient: restoreClient,
|
||||||
backupClient: backupClient,
|
backupClient: backupClient,
|
||||||
restorer: restorer,
|
restorer: restorer,
|
||||||
|
@ -319,7 +322,7 @@ func (controller *restoreController) getValidationErrors(itm *api.Restore) []str
|
||||||
}
|
}
|
||||||
|
|
||||||
func (controller *restoreController) fetchBackup(bucket, name string) (*api.Backup, error) {
|
func (controller *restoreController) fetchBackup(bucket, name string) (*api.Backup, error) {
|
||||||
backup, err := controller.backupLister.Backups(api.DefaultNamespace).Get(name)
|
backup, err := controller.backupLister.Backups(controller.namespace).Get(name)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return backup, nil
|
return backup, nil
|
||||||
}
|
}
|
||||||
|
@ -338,8 +341,10 @@ func (controller *restoreController) fetchBackup(bucket, name string) (*api.Back
|
||||||
|
|
||||||
// ResourceVersion needs to be cleared in order to create the object in the API
|
// ResourceVersion needs to be cleared in order to create the object in the API
|
||||||
backup.ResourceVersion = ""
|
backup.ResourceVersion = ""
|
||||||
|
// Clear out the namespace too, just in case
|
||||||
|
backup.Namespace = ""
|
||||||
|
|
||||||
created, createErr := controller.backupClient.Backups(api.DefaultNamespace).Create(backup)
|
created, createErr := controller.backupClient.Backups(controller.namespace).Create(backup)
|
||||||
if createErr != nil {
|
if createErr != nil {
|
||||||
logContext.WithError(errors.WithStack(createErr)).Error("Unable to create API object for Backup")
|
logContext.WithError(errors.WithStack(createErr)).Error("Unable to create API object for Backup")
|
||||||
} else {
|
} else {
|
||||||
|
@ -495,7 +500,7 @@ func patchRestore(original, updated *api.Restore, client arkv1client.RestoresGet
|
||||||
return nil, errors.Wrap(err, "error creating two-way merge patch for restore")
|
return nil, errors.Wrap(err, "error creating two-way merge patch for restore")
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := client.Restores(api.DefaultNamespace).Patch(original.Name, types.MergePatchType, patchBytes)
|
res, err := client.Restores(original.Namespace).Patch(original.Name, types.MergePatchType, patchBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error patching restore")
|
return nil, errors.Wrap(err, "error patching restore")
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,7 @@ func TestFetchBackup(t *testing.T) {
|
||||||
)
|
)
|
||||||
|
|
||||||
c := NewRestoreController(
|
c := NewRestoreController(
|
||||||
|
api.DefaultNamespace,
|
||||||
sharedInformers.Ark().V1().Restores(),
|
sharedInformers.Ark().V1().Restores(),
|
||||||
client.ArkV1(),
|
client.ArkV1(),
|
||||||
client.ArkV1(),
|
client.ArkV1(),
|
||||||
|
@ -249,6 +250,7 @@ func TestProcessRestore(t *testing.T) {
|
||||||
defer backupSvc.AssertExpectations(t)
|
defer backupSvc.AssertExpectations(t)
|
||||||
|
|
||||||
c := NewRestoreController(
|
c := NewRestoreController(
|
||||||
|
api.DefaultNamespace,
|
||||||
sharedInformers.Ark().V1().Restores(),
|
sharedInformers.Ark().V1().Restores(),
|
||||||
client.ArkV1(),
|
client.ArkV1(),
|
||||||
client.ArkV1(),
|
client.ArkV1(),
|
||||||
|
|
|
@ -45,6 +45,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type scheduleController struct {
|
type scheduleController struct {
|
||||||
|
namespace string
|
||||||
schedulesClient arkv1client.SchedulesGetter
|
schedulesClient arkv1client.SchedulesGetter
|
||||||
backupsClient arkv1client.BackupsGetter
|
backupsClient arkv1client.BackupsGetter
|
||||||
schedulesLister listers.ScheduleLister
|
schedulesLister listers.ScheduleLister
|
||||||
|
@ -57,6 +58,7 @@ type scheduleController struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewScheduleController(
|
func NewScheduleController(
|
||||||
|
namespace string,
|
||||||
schedulesClient arkv1client.SchedulesGetter,
|
schedulesClient arkv1client.SchedulesGetter,
|
||||||
backupsClient arkv1client.BackupsGetter,
|
backupsClient arkv1client.BackupsGetter,
|
||||||
schedulesInformer informers.ScheduleInformer,
|
schedulesInformer informers.ScheduleInformer,
|
||||||
|
@ -69,6 +71,7 @@ func NewScheduleController(
|
||||||
}
|
}
|
||||||
|
|
||||||
c := &scheduleController{
|
c := &scheduleController{
|
||||||
|
namespace: namespace,
|
||||||
schedulesClient: schedulesClient,
|
schedulesClient: schedulesClient,
|
||||||
backupsClient: backupsClient,
|
backupsClient: backupsClient,
|
||||||
schedulesLister: schedulesInformer.Lister(),
|
schedulesLister: schedulesInformer.Lister(),
|
||||||
|
@ -153,7 +156,7 @@ func (controller *scheduleController) Run(ctx context.Context, numWorkers int) e
|
||||||
}
|
}
|
||||||
|
|
||||||
func (controller *scheduleController) enqueueAllEnabledSchedules() {
|
func (controller *scheduleController) enqueueAllEnabledSchedules() {
|
||||||
schedules, err := controller.schedulesLister.Schedules(api.DefaultNamespace).List(labels.NewSelector())
|
schedules, err := controller.schedulesLister.Schedules(controller.namespace).List(labels.NewSelector())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
controller.logger.WithError(errors.WithStack(err)).Error("Error listing Schedules")
|
controller.logger.WithError(errors.WithStack(err)).Error("Error listing Schedules")
|
||||||
return
|
return
|
||||||
|
@ -388,7 +391,7 @@ func patchSchedule(original, updated *api.Schedule, client arkv1client.Schedules
|
||||||
return nil, errors.Wrap(err, "error creating two-way merge patch for schedule")
|
return nil, errors.Wrap(err, "error creating two-way merge patch for schedule")
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := client.Schedules(api.DefaultNamespace).Patch(original.Name, types.MergePatchType, patchBytes)
|
res, err := client.Schedules(original.Namespace).Patch(original.Name, types.MergePatchType, patchBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error patching schedule")
|
return nil, errors.Wrap(err, "error patching schedule")
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,6 +124,7 @@ func TestProcessSchedule(t *testing.T) {
|
||||||
)
|
)
|
||||||
|
|
||||||
c := NewScheduleController(
|
c := NewScheduleController(
|
||||||
|
"namespace",
|
||||||
client.ArkV1(),
|
client.ArkV1(),
|
||||||
client.ArkV1(),
|
client.ArkV1(),
|
||||||
sharedInformers.Ark().V1().Schedules(),
|
sharedInformers.Ark().V1().Schedules(),
|
||||||
|
|
Loading…
Reference in New Issue