mirror of
https://github.com/rancher/rke.git
synced 2025-08-18 14:57:03 +00:00
Add util command
This commit is contained in:
parent
91aed199f0
commit
a68a64c0ce
@ -790,15 +790,18 @@ func rebuildLocalAdminConfig(ctx context.Context, kubeCluster *Cluster) error {
|
|||||||
if len(kubeCluster.ControlPlaneHosts) == 0 {
|
if len(kubeCluster.ControlPlaneHosts) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
var activeControlPlaneHostFound bool
|
||||||
log.Infof(ctx, "[reconcile] Rebuilding and updating local kube config")
|
log.Infof(ctx, "[reconcile] Rebuilding and updating local kube config")
|
||||||
var workingConfig, newConfig string
|
var workingConfig, newConfig string
|
||||||
currentKubeConfig := kubeCluster.Certificates[pki.KubeAdminCertName]
|
currentKubeConfig := kubeCluster.Certificates[pki.KubeAdminCertName]
|
||||||
caCrt := kubeCluster.Certificates[pki.CACertName].Certificate
|
caCrt := kubeCluster.Certificates[pki.CACertName].Certificate
|
||||||
for _, cpHost := range kubeCluster.ControlPlaneHosts {
|
for _, cpHost := range kubeCluster.ControlPlaneHosts {
|
||||||
if (currentKubeConfig == pki.CertificatePKI{}) {
|
if (currentKubeConfig == pki.CertificatePKI{}) {
|
||||||
|
log.Debugf(ctx, "[reconcile] Rebuilding and updating local kube config, creating new address")
|
||||||
kubeCluster.Certificates = make(map[string]pki.CertificatePKI)
|
kubeCluster.Certificates = make(map[string]pki.CertificatePKI)
|
||||||
newConfig = getLocalAdminConfigWithNewAddress(kubeCluster.LocalKubeConfigPath, cpHost.Address, kubeCluster.ClusterName)
|
newConfig = getLocalAdminConfigWithNewAddress(kubeCluster.LocalKubeConfigPath, cpHost.Address, kubeCluster.ClusterName)
|
||||||
} else {
|
} else {
|
||||||
|
log.Debugf(ctx, "[reconcile] Rebuilding and updating local kube config, creating new kubeconfig")
|
||||||
kubeURL := fmt.Sprintf("https://%s:6443", cpHost.Address)
|
kubeURL := fmt.Sprintf("https://%s:6443", cpHost.Address)
|
||||||
caData := string(cert.EncodeCertPEM(caCrt))
|
caData := string(cert.EncodeCertPEM(caCrt))
|
||||||
crtData := string(cert.EncodeCertPEM(currentKubeConfig.Certificate))
|
crtData := string(cert.EncodeCertPEM(currentKubeConfig.Certificate))
|
||||||
@ -810,9 +813,14 @@ func rebuildLocalAdminConfig(ctx context.Context, kubeCluster *Cluster) error {
|
|||||||
}
|
}
|
||||||
workingConfig = newConfig
|
workingConfig = newConfig
|
||||||
if _, err := GetK8sVersion(kubeCluster.LocalKubeConfigPath, kubeCluster.K8sWrapTransport); err == nil {
|
if _, err := GetK8sVersion(kubeCluster.LocalKubeConfigPath, kubeCluster.K8sWrapTransport); err == nil {
|
||||||
log.Infof(ctx, "[reconcile] host [%s] is active master on the cluster", cpHost.Address)
|
log.Infof(ctx, "[reconcile] host [%s] is a control plane node with reachable Kubernetes API endpoint in the cluster", cpHost.Address)
|
||||||
|
activeControlPlaneHostFound = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
log.Warnf(ctx, "[reconcile] host [%s] is a control plane node without reachable Kubernetes API endpoint in the cluster", cpHost.Address)
|
||||||
|
}
|
||||||
|
if !activeControlPlaneHostFound {
|
||||||
|
log.Warnf(ctx, "[reconcile] no control plane node with reachable Kubernetes API endpoint in the cluster found")
|
||||||
}
|
}
|
||||||
currentKubeConfig.Config = workingConfig
|
currentKubeConfig.Config = workingConfig
|
||||||
kubeCluster.Certificates[pki.KubeAdminCertName] = currentKubeConfig
|
kubeCluster.Certificates[pki.KubeAdminCertName] = currentKubeConfig
|
||||||
|
@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/rancher/rke/k8s"
|
"github.com/rancher/rke/k8s"
|
||||||
"github.com/rancher/rke/log"
|
"github.com/rancher/rke/log"
|
||||||
"github.com/rancher/rke/pki"
|
"github.com/rancher/rke/pki"
|
||||||
|
"github.com/rancher/rke/services"
|
||||||
v3 "github.com/rancher/rke/types"
|
v3 "github.com/rancher/rke/types"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
@ -68,6 +69,19 @@ func (c *Cluster) GetClusterState(ctx context.Context, fullState *FullState) (*C
|
|||||||
return currentCluster, nil
|
return currentCluster, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Cluster) GetStateFileFromConfigMap(ctx context.Context) (string, error) {
|
||||||
|
kubeletImage := c.Services.Kubelet.Image
|
||||||
|
for _, host := range c.ControlPlaneHosts {
|
||||||
|
stateFile, err := services.RunGetStateFileFromConfigMap(ctx, host, c.PrivateRegistriesMap, kubeletImage)
|
||||||
|
if err != nil || stateFile == "" {
|
||||||
|
logrus.Infof("Could not get ConfigMap with cluster state from host [%s]", host.Address)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return stateFile, nil
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("Unable to get ConfigMap with cluster state from any Control Plane host")
|
||||||
|
}
|
||||||
|
|
||||||
func SaveFullStateToKubernetes(ctx context.Context, kubeCluster *Cluster, fullState *FullState) error {
|
func SaveFullStateToKubernetes(ctx context.Context, kubeCluster *Cluster, fullState *FullState) error {
|
||||||
k8sClient, err := k8s.NewClient(kubeCluster.LocalKubeConfigPath, kubeCluster.K8sWrapTransport)
|
k8sClient, err := k8s.NewClient(kubeCluster.LocalKubeConfigPath, kubeCluster.K8sWrapTransport)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
207
cmd/util.go
Normal file
207
cmd/util.go
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/rancher/rke/cluster"
|
||||||
|
"github.com/rancher/rke/hosts"
|
||||||
|
"github.com/rancher/rke/k8s"
|
||||||
|
"github.com/rancher/rke/pki"
|
||||||
|
v3 "github.com/rancher/rke/types"
|
||||||
|
"github.com/rancher/rke/util"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func UtilCommand() cli.Command {
|
||||||
|
utilCfgFlags := []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "config",
|
||||||
|
Usage: "Specify an alternate cluster YAML file",
|
||||||
|
Value: pki.ClusterConfig,
|
||||||
|
EnvVar: "RKE_CONFIG",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
utilFlags := append(utilCfgFlags, commonFlags...)
|
||||||
|
|
||||||
|
return cli.Command{
|
||||||
|
Name: "util",
|
||||||
|
Usage: "Various utilities to retrieve cluster related files and troubleshoot",
|
||||||
|
Subcommands: cli.Commands{
|
||||||
|
cli.Command{
|
||||||
|
Name: "get-state-file",
|
||||||
|
Usage: "Retrieve state file from cluster",
|
||||||
|
Action: getStateFile,
|
||||||
|
Flags: utilFlags,
|
||||||
|
},
|
||||||
|
cli.Command{
|
||||||
|
Name: "get-kubeconfig",
|
||||||
|
Usage: "Retrieve kubeconfig file from cluster state",
|
||||||
|
Action: getKubeconfigFile,
|
||||||
|
Flags: utilFlags,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getKubeconfigFile(ctx *cli.Context) error {
|
||||||
|
logrus.Infof("Creating new kubeconfig file")
|
||||||
|
// Check if we can successfully connect to the cluster using the existing kubeconfig file
|
||||||
|
clusterFile, clusterFilePath, err := resolveClusterFile(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to resolve cluster file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// setting up the flags
|
||||||
|
flags := cluster.GetExternalFlags(false, false, false, false, "", clusterFilePath)
|
||||||
|
rkeConfig, err := cluster.ParseConfig(clusterFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to parse cluster file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rkeConfig, err = setOptionsFromCLI(ctx, rkeConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
clusterState, err := cluster.ReadStateFile(context.Background(), cluster.GetStateFilePath(flags.ClusterFilePath, flags.ConfigDir))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creating temp cluster to check if snapshot archive contains state file and retrieve it
|
||||||
|
tempCluster, err := cluster.InitClusterObject(context.Background(), rkeConfig, flags, "")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move current kubeconfig file
|
||||||
|
err = util.CopyFileWithPrefix(tempCluster.LocalKubeConfigPath, "kube_config")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
kubeCluster, _ := tempCluster.GetClusterState(context.Background(), clusterState)
|
||||||
|
|
||||||
|
if err := cluster.RebuildKubeconfig(context.Background(), kubeCluster); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getStateFile(ctx *cli.Context) error {
|
||||||
|
logrus.Infof("Retrieving state file from cluster")
|
||||||
|
// Check if we can successfully connect to the cluster using the existing kubeconfig file
|
||||||
|
localKubeConfig := pki.GetLocalKubeConfig(ctx.String("config"), "")
|
||||||
|
clusterFile, clusterFilePath, err := resolveClusterFile(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to resolve cluster file: %v", err)
|
||||||
|
}
|
||||||
|
// setting up the flags
|
||||||
|
flags := cluster.GetExternalFlags(false, false, false, false, "", clusterFilePath)
|
||||||
|
|
||||||
|
// not going to use a k8s dialer here.. this is a CLI command
|
||||||
|
serverVersion, err := cluster.GetK8sVersion(localKubeConfig, nil)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Infof("Unable to connect to server using kubeconfig, trying to get state from Control Plane node(s), error: %v", err)
|
||||||
|
// We need to retrieve the state file using Docker on the node(s)
|
||||||
|
|
||||||
|
rkeConfig, err := cluster.ParseConfig(clusterFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to parse cluster file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rkeConfig, err = setOptionsFromCLI(ctx, rkeConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, _, _, _, err = RetrieveClusterStateConfigMap(context.Background(), rkeConfig, hosts.DialersOptions{}, flags, map[string]interface{}{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
logrus.Infof("Successfully connected to server using kubeconfig, retrieved server version [%s]", serverVersion)
|
||||||
|
// Retrieve full-cluster-state configmap
|
||||||
|
k8sClient, err := k8s.NewClient(localKubeConfig, nil)
|
||||||
|
cfgMap, err := k8s.GetConfigMap(k8sClient, cluster.FullStateConfigMapName)
|
||||||
|
clusterData := cfgMap.Data[cluster.FullStateConfigMapName]
|
||||||
|
rkeFullState := &cluster.FullState{}
|
||||||
|
if err = json.Unmarshal([]byte(clusterData), rkeFullState); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move current state file
|
||||||
|
stateFilePath := cluster.GetStateFilePath(flags.ClusterFilePath, flags.ConfigDir)
|
||||||
|
err = util.ReplaceFileWithBackup(stateFilePath, "rkestate")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write new state file
|
||||||
|
err = rkeFullState.WriteStateFile(context.Background(), stateFilePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RetrieveClusterStateConfigMap(
|
||||||
|
ctx context.Context,
|
||||||
|
rkeConfig *v3.RancherKubernetesEngineConfig,
|
||||||
|
dialersOptions hosts.DialersOptions,
|
||||||
|
flags cluster.ExternalFlags,
|
||||||
|
data map[string]interface{}) (string, string, string, string, map[string]pki.CertificatePKI, error) {
|
||||||
|
var APIURL, caCrt, clientCert, clientKey string
|
||||||
|
|
||||||
|
rkeFullState := &cluster.FullState{}
|
||||||
|
|
||||||
|
// Creating temp cluster to check if snapshot archive contains state file and retrieve it
|
||||||
|
tempCluster, err := cluster.InitClusterObject(ctx, rkeConfig, flags, "")
|
||||||
|
if err != nil {
|
||||||
|
return APIURL, caCrt, clientCert, clientKey, nil, err
|
||||||
|
}
|
||||||
|
if err := tempCluster.SetupDialers(ctx, dialersOptions); err != nil {
|
||||||
|
return APIURL, caCrt, clientCert, clientKey, nil, err
|
||||||
|
}
|
||||||
|
if err := tempCluster.TunnelHosts(ctx, flags); err != nil {
|
||||||
|
return APIURL, caCrt, clientCert, clientKey, nil, err
|
||||||
|
}
|
||||||
|
// Get ConfigMap containing cluster state from Control Plane Hosts
|
||||||
|
stateFile, err := tempCluster.GetStateFileFromConfigMap(ctx)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return APIURL, caCrt, clientCert, clientKey, nil, err
|
||||||
|
}
|
||||||
|
rkeFullState, err = cluster.StringToFullState(ctx, stateFile)
|
||||||
|
|
||||||
|
// Move current state file
|
||||||
|
stateFilePath := cluster.GetStateFilePath(flags.ClusterFilePath, flags.ConfigDir)
|
||||||
|
err = util.ReplaceFileWithBackup(stateFilePath, "rkestate")
|
||||||
|
if err != nil {
|
||||||
|
return APIURL, caCrt, clientCert, clientKey, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = rkeFullState.WriteStateFile(context.Background(), stateFilePath)
|
||||||
|
if err != nil {
|
||||||
|
return APIURL, caCrt, clientCert, clientKey, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move current kubeconfig file
|
||||||
|
err = util.CopyFileWithPrefix(tempCluster.LocalKubeConfigPath, "kube_config")
|
||||||
|
if err != nil {
|
||||||
|
return APIURL, caCrt, clientCert, clientKey, nil, err
|
||||||
|
}
|
||||||
|
kubeCluster, _ := tempCluster.GetClusterState(ctx, rkeFullState)
|
||||||
|
|
||||||
|
if err := cluster.RebuildKubeconfig(ctx, kubeCluster); err != nil {
|
||||||
|
return APIURL, caCrt, clientCert, clientKey, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return APIURL, caCrt, clientCert, clientKey, nil, nil
|
||||||
|
}
|
1
main.go
1
main.go
@ -62,6 +62,7 @@ func mainErr() error {
|
|||||||
cmd.EtcdCommand(),
|
cmd.EtcdCommand(),
|
||||||
cmd.CertificateCommand(),
|
cmd.CertificateCommand(),
|
||||||
cmd.EncryptionCommand(),
|
cmd.EncryptionCommand(),
|
||||||
|
cmd.UtilCommand(),
|
||||||
}
|
}
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = []cli.Flag{
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
|
@ -183,6 +183,7 @@ func doRunDeployer(ctx context.Context, host *hosts.Host, containerEnv []string,
|
|||||||
|
|
||||||
func DeployAdminConfig(ctx context.Context, kubeConfig, localConfigPath string) error {
|
func DeployAdminConfig(ctx context.Context, kubeConfig, localConfigPath string) error {
|
||||||
if len(kubeConfig) == 0 {
|
if len(kubeConfig) == 0 {
|
||||||
|
logrus.Infof("kubeConfig is empty")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
logrus.Debugf("Deploying admin Kubeconfig locally at [%s]", localConfigPath)
|
logrus.Debugf("Deploying admin Kubeconfig locally at [%s]", localConfigPath)
|
||||||
|
@ -3,9 +3,11 @@ package services
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/rancher/rke/docker"
|
"github.com/rancher/rke/docker"
|
||||||
"github.com/rancher/rke/hosts"
|
"github.com/rancher/rke/hosts"
|
||||||
@ -366,3 +368,37 @@ func isControlPlaneHostUpgradable(ctx context.Context, host *hosts.Host, process
|
|||||||
logrus.Debugf("[%s] Host %v is not upgradable", ControlRole, host.HostnameOverride)
|
logrus.Debugf("[%s] Host %v is not upgradable", ControlRole, host.HostnameOverride)
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RunGetStateFileFromConfigMap(ctx context.Context, controlPlaneHost *hosts.Host, prsMap map[string]v3.PrivateRegistry, dockerImage string) (string, error) {
|
||||||
|
imageCfg := &container.Config{
|
||||||
|
Entrypoint: []string{"bash"},
|
||||||
|
Cmd: []string{
|
||||||
|
"-c",
|
||||||
|
"kubectl --kubeconfig /etc/kubernetes/ssl/kubecfg-kube-node.yaml -n kube-system get configmap full-cluster-state -o json | jq -r .data.\\\"full-cluster-state\\\" | jq -r . > /tmp/configmap.cluster.rkestate",
|
||||||
|
},
|
||||||
|
Image: dockerImage,
|
||||||
|
}
|
||||||
|
hostCfg := &container.HostConfig{
|
||||||
|
Binds: []string{
|
||||||
|
fmt.Sprintf("%s:/etc/kubernetes:z", path.Join(controlPlaneHost.PrefixPath, "/etc/kubernetes")),
|
||||||
|
},
|
||||||
|
NetworkMode: container.NetworkMode("host"),
|
||||||
|
RestartPolicy: container.RestartPolicy{Name: "no"},
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := docker.DoRemoveContainer(ctx, controlPlaneHost.DClient, ControlPlaneConfigMapStateFileContainerName, controlPlaneHost.Address); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if err := docker.DoRunOnetimeContainer(ctx, controlPlaneHost.DClient, imageCfg, hostCfg, ControlPlaneConfigMapStateFileContainerName, controlPlaneHost.Address, ControlRole, prsMap); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
statefile, err := docker.ReadFileFromContainer(ctx, controlPlaneHost.DClient, controlPlaneHost.Address, ControlPlaneConfigMapStateFileContainerName, "/tmp/configmap.cluster.rkestate")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if err := docker.DoRemoveContainer(ctx, controlPlaneHost.DClient, ControlPlaneConfigMapStateFileContainerName, controlPlaneHost.Address); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return statefile, nil
|
||||||
|
}
|
||||||
|
@ -36,6 +36,7 @@ const (
|
|||||||
EtcdServeBackupContainerName = "etcd-Serve-backup"
|
EtcdServeBackupContainerName = "etcd-Serve-backup"
|
||||||
EtcdChecksumContainerName = "etcd-checksum-checker"
|
EtcdChecksumContainerName = "etcd-checksum-checker"
|
||||||
EtcdStateFileContainerName = "etcd-extract-statefile"
|
EtcdStateFileContainerName = "etcd-extract-statefile"
|
||||||
|
ControlPlaneConfigMapStateFileContainerName = "extract-statefile-configmap"
|
||||||
NginxProxyContainerName = "nginx-proxy"
|
NginxProxyContainerName = "nginx-proxy"
|
||||||
SidekickContainerName = "service-sidekick"
|
SidekickContainerName = "service-sidekick"
|
||||||
LogLinkContainerName = "rke-log-linker"
|
LogLinkContainerName = "rke-log-linker"
|
||||||
|
64
util/util.go
64
util/util.go
@ -2,6 +2,8 @@ package util
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -180,3 +182,65 @@ func CleanWindowsPath(s string) string {
|
|||||||
}
|
}
|
||||||
return strings.Join(new, "\\")
|
return strings.Join(new, "\\")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ReplaceFileWithBackup(originalFile, prefixBackupFile string) error {
|
||||||
|
fileExists, err := IsFileExists(originalFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !fileExists {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
tmpfile, err := ioutil.TempFile(".", prefixBackupFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = os.Rename(originalFile, tmpfile.Name())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logrus.Infof("Moved file [%s] to new location [%s] as back-up", originalFile, tmpfile.Name())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CopyFileWithPrefix(originalFile, prefixDestFile string) error {
|
||||||
|
fileExists, err := IsFileExists(originalFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !fileExists {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceFileStat, err := os.Stat(originalFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !sourceFileStat.Mode().IsRegular() {
|
||||||
|
return fmt.Errorf("%s is not a regular file", originalFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
source, err := os.Open(originalFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer source.Close()
|
||||||
|
|
||||||
|
destFile, err := ioutil.TempFile(".", prefixDestFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
destination, err := os.Create(destFile.Name())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer destination.Close()
|
||||||
|
_, err = io.Copy(destination, source)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logrus.Infof("Copied file [%s] to new location [%s] as back-up", originalFile, destFile.Name())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user