mirror of
https://github.com/kubenetworks/kubevpn.git
synced 2025-09-26 19:31:17 +08:00
refactor: remove target-kubeconfig of clone mode
This commit is contained in:
@@ -36,9 +36,9 @@ func CmdClone(f cmdutil.Factory) *cobra.Command {
|
||||
var imagePullSecretName string
|
||||
cmd := &cobra.Command{
|
||||
Use: "clone",
|
||||
Short: i18n.T("Clone workloads to run in target-kubeconfig cluster with same volume、env、and network"),
|
||||
Short: i18n.T("Clone workloads to run in same namespace with same volume、env、and network"),
|
||||
Long: templates.LongDesc(i18n.T(`
|
||||
Clone workloads to run into target-kubeconfig cluster with same volume、env、and network
|
||||
Clone workloads to run in same namespace with same volume、env、and network
|
||||
|
||||
In this way, you can startup another deployment in same cluster or not, but with different image version,
|
||||
it also supports service mesh proxy. only traffic with special header will hit to cloned_resource.
|
||||
@@ -98,8 +98,6 @@ func CmdClone(f cmdutil.Factory) *cobra.Command {
|
||||
}
|
||||
return cmdutil.UsageErrorf(cmd, usageString)
|
||||
}
|
||||
// special empty string, eg: --target-registry ""
|
||||
options.IsChangeTargetRegistry = cmd.Flags().Changed("target-registry")
|
||||
|
||||
if syncDir != "" {
|
||||
local, remote, err := util.ParseDirMapping(syncDir)
|
||||
@@ -122,26 +120,22 @@ func CmdClone(f cmdutil.Factory) *cobra.Command {
|
||||
}
|
||||
}
|
||||
req := &rpc.CloneRequest{
|
||||
KubeconfigBytes: string(bytes),
|
||||
Namespace: ns,
|
||||
Headers: options.Headers,
|
||||
Workloads: args,
|
||||
ExtraRoute: extraRoute.ToRPC(),
|
||||
OriginKubeconfigPath: util.GetKubeConfigPath(f),
|
||||
Engine: string(options.Engine),
|
||||
SshJump: sshConf.ToRPC(),
|
||||
TargetKubeconfig: options.TargetKubeconfig,
|
||||
TargetNamespace: options.TargetNamespace,
|
||||
TargetContainer: options.TargetContainer,
|
||||
TargetImage: options.TargetImage,
|
||||
TargetRegistry: options.TargetRegistry,
|
||||
IsChangeTargetRegistry: options.IsChangeTargetRegistry,
|
||||
TransferImage: transferImage,
|
||||
Image: config.Image,
|
||||
ImagePullSecretName: imagePullSecretName,
|
||||
Level: int32(util.If(config.Debug, log.DebugLevel, log.InfoLevel)),
|
||||
LocalDir: options.LocalDir,
|
||||
RemoteDir: options.RemoteDir,
|
||||
KubeconfigBytes: string(bytes),
|
||||
Namespace: ns,
|
||||
Headers: options.Headers,
|
||||
Workloads: args,
|
||||
ExtraRoute: extraRoute.ToRPC(),
|
||||
OriginKubeconfigPath: util.GetKubeConfigPath(f),
|
||||
Engine: string(options.Engine),
|
||||
SshJump: sshConf.ToRPC(),
|
||||
TargetContainer: options.TargetContainer,
|
||||
TargetImage: options.TargetImage,
|
||||
TransferImage: transferImage,
|
||||
Image: config.Image,
|
||||
ImagePullSecretName: imagePullSecretName,
|
||||
Level: int32(util.If(config.Debug, log.DebugLevel, log.InfoLevel)),
|
||||
LocalDir: options.LocalDir,
|
||||
RemoteDir: options.RemoteDir,
|
||||
}
|
||||
cli, err := daemon.GetClient(false)
|
||||
if err != nil {
|
||||
@@ -168,9 +162,6 @@ func CmdClone(f cmdutil.Factory) *cobra.Command {
|
||||
|
||||
cmdutil.AddContainerVarFlags(cmd, &options.TargetContainer, options.TargetContainer)
|
||||
cmd.Flags().StringVar(&options.TargetImage, "target-image", "", "Clone container use this image to startup container, if not special, use origin image")
|
||||
cmd.Flags().StringVar(&options.TargetNamespace, "target-namespace", "", "Clone workloads in this namespace, if not special, use origin namespace")
|
||||
cmd.Flags().StringVar(&options.TargetKubeconfig, "target-kubeconfig", "", "Clone workloads will create in this cluster, if not special, use origin cluster")
|
||||
cmd.Flags().StringVar(&options.TargetRegistry, "target-registry", "", "Clone workloads will create this registry domain to replace origin registry, if not special, use origin registry")
|
||||
cmd.Flags().StringVar(&syncDir, "sync", "", "Sync local dir to remote pod dir. format: LOCAL_DIR:REMOTE_DIR, eg: ~/code:/app/code")
|
||||
|
||||
handler.AddExtraRoute(cmd.Flags(), extraRoute)
|
||||
|
@@ -28,8 +28,9 @@ func CmdLeave(f cmdutil.Factory) *cobra.Command {
|
||||
`)),
|
||||
Example: templates.Examples(i18n.T(`
|
||||
# leave proxy resource and restore it to origin
|
||||
kubevpn leave deployment/authors
|
||||
kubevpn leave deployment/authors-clone-645d7
|
||||
`)),
|
||||
Args: cobra.MatchAll(cobra.OnlyValidArgs, cobra.MinimumNArgs(1)),
|
||||
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
return daemon.StartupDaemon(cmd.Context())
|
||||
},
|
||||
|
@@ -2,7 +2,6 @@ package cmds
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
@@ -91,6 +90,7 @@ func CmdProxy(f cmdutil.Factory) *cobra.Command {
|
||||
# Auto proxy container port to same local port, and auto detect protocol
|
||||
kubevpn proxy deployment/productpage
|
||||
`)),
|
||||
Args: cobra.MatchAll(cobra.OnlyValidArgs, cobra.MinimumNArgs(1)),
|
||||
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
plog.InitLoggerForClient()
|
||||
if err = daemon.StartupDaemon(cmd.Context()); err != nil {
|
||||
@@ -102,16 +102,6 @@ func CmdProxy(f cmdutil.Factory) *cobra.Command {
|
||||
return err
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if len(args) == 0 {
|
||||
fmt.Fprintf(os.Stdout, "You must specify the type of resource to proxy. %s\n\n", cmdutil.SuggestAPIResources("kubevpn"))
|
||||
fullCmdName := cmd.Parent().CommandPath()
|
||||
usageString := "Required resource not specified."
|
||||
if len(fullCmdName) > 0 && cmdutil.IsSiblingCommandExists(cmd, "explain") {
|
||||
usageString = fmt.Sprintf("%s\nUse \"%s explain <resource>\" for a detailed description of that resource (e.g. %[2]s explain pods).", usageString, fullCmdName)
|
||||
}
|
||||
return cmdutil.UsageErrorf(cmd, usageString)
|
||||
}
|
||||
|
||||
bytes, ns, err := util.ConvertToKubeConfigBytes(f)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@@ -204,7 +204,7 @@ func genCloneMsg(w *tabwriter.Writer, list []*rpc.Status) {
|
||||
|
||||
_, _ = fmt.Fprintf(w, "\n")
|
||||
w.SetRememberedWidths(nil)
|
||||
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", "ID", "Namespace", "Name", "Headers", "ToName", "ToKubeconfig", "ToNamespace", "SyncthingGUI")
|
||||
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\n", "ID", "Namespace", "Name", "Headers", "ToName", "SyncthingGUI")
|
||||
for _, c := range list {
|
||||
for _, clone := range c.CloneList {
|
||||
//_, _ = fmt.Fprintf(w, "%s\n", clone.Workload)
|
||||
@@ -216,14 +216,12 @@ func genCloneMsg(w *tabwriter.Writer, list []*rpc.Status) {
|
||||
if len(headers) == 0 {
|
||||
headers = []string{"*"}
|
||||
}
|
||||
_, _ = fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
|
||||
_, _ = fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t%s\n",
|
||||
c.ID,
|
||||
clone.Namespace,
|
||||
clone.Workload,
|
||||
strings.Join(headers, ","),
|
||||
rule.DstWorkload,
|
||||
rule.DstKubeconfig,
|
||||
rule.DstNamespace,
|
||||
clone.SyncthingGUIAddr,
|
||||
)
|
||||
}
|
||||
|
@@ -51,15 +51,11 @@ func (svr *Server) Clone(req *rpc.CloneRequest, resp rpc.Daemon_CloneServer) (er
|
||||
Engine: config.Engine(req.Engine),
|
||||
OriginKubeconfigPath: req.OriginKubeconfigPath,
|
||||
|
||||
TargetKubeconfig: req.TargetKubeconfig,
|
||||
TargetNamespace: req.TargetNamespace,
|
||||
TargetContainer: req.TargetContainer,
|
||||
TargetImage: req.TargetImage,
|
||||
TargetRegistry: req.TargetRegistry,
|
||||
IsChangeTargetRegistry: req.IsChangeTargetRegistry,
|
||||
TargetWorkloadNames: map[string]string{},
|
||||
LocalDir: req.LocalDir,
|
||||
RemoteDir: req.RemoteDir,
|
||||
TargetContainer: req.TargetContainer,
|
||||
TargetImage: req.TargetImage,
|
||||
TargetWorkloadNames: map[string]string{},
|
||||
LocalDir: req.LocalDir,
|
||||
RemoteDir: req.RemoteDir,
|
||||
}
|
||||
file, err := util.ConvertToTempKubeconfigFile([]byte(req.KubeconfigBytes))
|
||||
if err != nil {
|
||||
|
@@ -147,11 +147,8 @@ func gen(ctx context.Context, connect *handler.ConnectOptions, clone *handler.Cl
|
||||
SyncthingGUIAddr: clone.GetSyncthingGUIAddr(),
|
||||
RuleList: []*rpc.CloneRule{
|
||||
{
|
||||
DstCluster: util.GetKubeconfigCluster(clone.GetFactory()),
|
||||
Headers: clone.Headers,
|
||||
DstWorkload: clone.TargetWorkloadNames[workload],
|
||||
DstKubeconfig: clone.TargetKubeconfig,
|
||||
DstNamespace: clone.TargetNamespace,
|
||||
Headers: clone.Headers,
|
||||
DstWorkload: clone.TargetWorkloadNames[workload],
|
||||
},
|
||||
},
|
||||
})
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -150,12 +150,8 @@ message CloneRequest {
|
||||
SshJump SshJump = 8;
|
||||
|
||||
// target cluster info
|
||||
string TargetKubeconfig = 9;
|
||||
string TargetNamespace = 10;
|
||||
string TargetContainer = 11;
|
||||
string TargetImage = 12;
|
||||
string TargetRegistry = 13;
|
||||
bool IsChangeTargetRegistry = 14;
|
||||
|
||||
// transfer image
|
||||
bool TransferImage = 15;
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.6
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v5.29.3
|
||||
// source: dhcpserver.proto
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -22,18 +21,21 @@ const (
|
||||
)
|
||||
|
||||
type RentIPRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
PodName string `protobuf:"bytes,1,opt,name=PodName,proto3" json:"PodName,omitempty"`
|
||||
PodNamespace string `protobuf:"bytes,2,opt,name=PodNamespace,proto3" json:"PodNamespace,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
PodName string `protobuf:"bytes,1,opt,name=PodName,proto3" json:"PodName,omitempty"`
|
||||
PodNamespace string `protobuf:"bytes,2,opt,name=PodNamespace,proto3" json:"PodNamespace,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RentIPRequest) Reset() {
|
||||
*x = RentIPRequest{}
|
||||
mi := &file_dhcpserver_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_dhcpserver_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *RentIPRequest) String() string {
|
||||
@@ -44,7 +46,7 @@ func (*RentIPRequest) ProtoMessage() {}
|
||||
|
||||
func (x *RentIPRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_dhcpserver_proto_msgTypes[0]
|
||||
if x != nil {
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
@@ -74,18 +76,21 @@ func (x *RentIPRequest) GetPodNamespace() string {
|
||||
}
|
||||
|
||||
type RentIPResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
IPv4CIDR string `protobuf:"bytes,1,opt,name=IPv4CIDR,proto3" json:"IPv4CIDR,omitempty"`
|
||||
IPv6CIDR string `protobuf:"bytes,2,opt,name=IPv6CIDR,proto3" json:"IPv6CIDR,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
IPv4CIDR string `protobuf:"bytes,1,opt,name=IPv4CIDR,proto3" json:"IPv4CIDR,omitempty"`
|
||||
IPv6CIDR string `protobuf:"bytes,2,opt,name=IPv6CIDR,proto3" json:"IPv6CIDR,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RentIPResponse) Reset() {
|
||||
*x = RentIPResponse{}
|
||||
mi := &file_dhcpserver_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_dhcpserver_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *RentIPResponse) String() string {
|
||||
@@ -96,7 +101,7 @@ func (*RentIPResponse) ProtoMessage() {}
|
||||
|
||||
func (x *RentIPResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_dhcpserver_proto_msgTypes[1]
|
||||
if x != nil {
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
@@ -126,20 +131,23 @@ func (x *RentIPResponse) GetIPv6CIDR() string {
|
||||
}
|
||||
|
||||
type ReleaseIPRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
PodName string `protobuf:"bytes,1,opt,name=PodName,proto3" json:"PodName,omitempty"`
|
||||
PodNamespace string `protobuf:"bytes,2,opt,name=PodNamespace,proto3" json:"PodNamespace,omitempty"`
|
||||
IPv4CIDR string `protobuf:"bytes,3,opt,name=IPv4CIDR,proto3" json:"IPv4CIDR,omitempty"`
|
||||
IPv6CIDR string `protobuf:"bytes,4,opt,name=IPv6CIDR,proto3" json:"IPv6CIDR,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
PodName string `protobuf:"bytes,1,opt,name=PodName,proto3" json:"PodName,omitempty"`
|
||||
PodNamespace string `protobuf:"bytes,2,opt,name=PodNamespace,proto3" json:"PodNamespace,omitempty"`
|
||||
IPv4CIDR string `protobuf:"bytes,3,opt,name=IPv4CIDR,proto3" json:"IPv4CIDR,omitempty"`
|
||||
IPv6CIDR string `protobuf:"bytes,4,opt,name=IPv6CIDR,proto3" json:"IPv6CIDR,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ReleaseIPRequest) Reset() {
|
||||
*x = ReleaseIPRequest{}
|
||||
mi := &file_dhcpserver_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_dhcpserver_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ReleaseIPRequest) String() string {
|
||||
@@ -150,7 +158,7 @@ func (*ReleaseIPRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ReleaseIPRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_dhcpserver_proto_msgTypes[2]
|
||||
if x != nil {
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
@@ -194,17 +202,20 @@ func (x *ReleaseIPRequest) GetIPv6CIDR() string {
|
||||
}
|
||||
|
||||
type ReleaseIPResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ReleaseIPResponse) Reset() {
|
||||
*x = ReleaseIPResponse{}
|
||||
mi := &file_dhcpserver_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_dhcpserver_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ReleaseIPResponse) String() string {
|
||||
@@ -215,7 +226,7 @@ func (*ReleaseIPResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ReleaseIPResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_dhcpserver_proto_msgTypes[3]
|
||||
if x != nil {
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
@@ -239,40 +250,55 @@ func (x *ReleaseIPResponse) GetMessage() string {
|
||||
|
||||
var File_dhcpserver_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_dhcpserver_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x10dhcpserver.proto\x12\x03rpc\"M\n" +
|
||||
"\rRentIPRequest\x12\x18\n" +
|
||||
"\aPodName\x18\x01 \x01(\tR\aPodName\x12\"\n" +
|
||||
"\fPodNamespace\x18\x02 \x01(\tR\fPodNamespace\"H\n" +
|
||||
"\x0eRentIPResponse\x12\x1a\n" +
|
||||
"\bIPv4CIDR\x18\x01 \x01(\tR\bIPv4CIDR\x12\x1a\n" +
|
||||
"\bIPv6CIDR\x18\x02 \x01(\tR\bIPv6CIDR\"\x88\x01\n" +
|
||||
"\x10ReleaseIPRequest\x12\x18\n" +
|
||||
"\aPodName\x18\x01 \x01(\tR\aPodName\x12\"\n" +
|
||||
"\fPodNamespace\x18\x02 \x01(\tR\fPodNamespace\x12\x1a\n" +
|
||||
"\bIPv4CIDR\x18\x03 \x01(\tR\bIPv4CIDR\x12\x1a\n" +
|
||||
"\bIPv6CIDR\x18\x04 \x01(\tR\bIPv6CIDR\"-\n" +
|
||||
"\x11ReleaseIPResponse\x12\x18\n" +
|
||||
"\amessage\x18\x01 \x01(\tR\amessage2y\n" +
|
||||
"\x04DHCP\x123\n" +
|
||||
"\x06RentIP\x12\x12.rpc.RentIPRequest\x1a\x13.rpc.RentIPResponse\"\x00\x12<\n" +
|
||||
"\tReleaseIP\x12\x15.rpc.ReleaseIPRequest\x1a\x16.rpc.ReleaseIPResponse\"\x00B\aZ\x05.;rpcb\x06proto3"
|
||||
var file_dhcpserver_proto_rawDesc = []byte{
|
||||
0x0a, 0x10, 0x64, 0x68, 0x63, 0x70, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x12, 0x03, 0x72, 0x70, 0x63, 0x22, 0x4d, 0x0a, 0x0d, 0x52, 0x65, 0x6e, 0x74, 0x49,
|
||||
0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x6f, 0x64, 0x4e,
|
||||
0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x50, 0x6f, 0x64, 0x4e, 0x61,
|
||||
0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x50, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
|
||||
0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x50, 0x6f, 0x64, 0x4e, 0x61, 0x6d,
|
||||
0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x48, 0x0a, 0x0e, 0x52, 0x65, 0x6e, 0x74, 0x49, 0x50,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x49, 0x50, 0x76, 0x34,
|
||||
0x43, 0x49, 0x44, 0x52, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x49, 0x50, 0x76, 0x34,
|
||||
0x43, 0x49, 0x44, 0x52, 0x12, 0x1a, 0x0a, 0x08, 0x49, 0x50, 0x76, 0x36, 0x43, 0x49, 0x44, 0x52,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x49, 0x50, 0x76, 0x36, 0x43, 0x49, 0x44, 0x52,
|
||||
0x22, 0x88, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x50, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x50, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12,
|
||||
0x22, 0x0a, 0x0c, 0x50, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x50, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70,
|
||||
0x61, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x49, 0x50, 0x76, 0x34, 0x43, 0x49, 0x44, 0x52, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x49, 0x50, 0x76, 0x34, 0x43, 0x49, 0x44, 0x52, 0x12,
|
||||
0x1a, 0x0a, 0x08, 0x49, 0x50, 0x76, 0x36, 0x43, 0x49, 0x44, 0x52, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x08, 0x49, 0x50, 0x76, 0x36, 0x43, 0x49, 0x44, 0x52, 0x22, 0x2d, 0x0a, 0x11, 0x52,
|
||||
0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x79, 0x0a, 0x04, 0x44, 0x48,
|
||||
0x43, 0x50, 0x12, 0x33, 0x0a, 0x06, 0x52, 0x65, 0x6e, 0x74, 0x49, 0x50, 0x12, 0x12, 0x2e, 0x72,
|
||||
0x70, 0x63, 0x2e, 0x52, 0x65, 0x6e, 0x74, 0x49, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x13, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6e, 0x74, 0x49, 0x50, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x09, 0x52, 0x65, 0x6c, 0x65, 0x61,
|
||||
0x73, 0x65, 0x49, 0x50, 0x12, 0x15, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61,
|
||||
0x73, 0x65, 0x49, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x70,
|
||||
0x63, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x07, 0x5a, 0x05, 0x2e, 0x3b, 0x72, 0x70, 0x63, 0x62, 0x06,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_dhcpserver_proto_rawDescOnce sync.Once
|
||||
file_dhcpserver_proto_rawDescData []byte
|
||||
file_dhcpserver_proto_rawDescData = file_dhcpserver_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_dhcpserver_proto_rawDescGZIP() []byte {
|
||||
file_dhcpserver_proto_rawDescOnce.Do(func() {
|
||||
file_dhcpserver_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_dhcpserver_proto_rawDesc), len(file_dhcpserver_proto_rawDesc)))
|
||||
file_dhcpserver_proto_rawDescData = protoimpl.X.CompressGZIP(file_dhcpserver_proto_rawDescData)
|
||||
})
|
||||
return file_dhcpserver_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_dhcpserver_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
||||
var file_dhcpserver_proto_goTypes = []any{
|
||||
var file_dhcpserver_proto_goTypes = []interface{}{
|
||||
(*RentIPRequest)(nil), // 0: rpc.RentIPRequest
|
||||
(*RentIPResponse)(nil), // 1: rpc.RentIPResponse
|
||||
(*ReleaseIPRequest)(nil), // 2: rpc.ReleaseIPRequest
|
||||
@@ -295,11 +321,61 @@ func file_dhcpserver_proto_init() {
|
||||
if File_dhcpserver_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_dhcpserver_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*RentIPRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_dhcpserver_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*RentIPResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_dhcpserver_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ReleaseIPRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_dhcpserver_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ReleaseIPResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_dhcpserver_proto_rawDesc), len(file_dhcpserver_proto_rawDesc)),
|
||||
RawDescriptor: file_dhcpserver_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 4,
|
||||
NumExtensions: 0,
|
||||
@@ -310,6 +386,7 @@ func file_dhcpserver_proto_init() {
|
||||
MessageInfos: file_dhcpserver_proto_msgTypes,
|
||||
}.Build()
|
||||
File_dhcpserver_proto = out.File
|
||||
file_dhcpserver_proto_rawDesc = nil
|
||||
file_dhcpserver_proto_goTypes = nil
|
||||
file_dhcpserver_proto_depIdxs = nil
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc v5.29.3
|
||||
// source: dhcpserver.proto
|
||||
|
||||
@@ -15,8 +15,8 @@ import (
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
const (
|
||||
DHCP_RentIP_FullMethodName = "/rpc.DHCP/RentIP"
|
||||
@@ -40,9 +40,8 @@ func NewDHCPClient(cc grpc.ClientConnInterface) DHCPClient {
|
||||
}
|
||||
|
||||
func (c *dHCPClient) RentIP(ctx context.Context, in *RentIPRequest, opts ...grpc.CallOption) (*RentIPResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(RentIPResponse)
|
||||
err := c.cc.Invoke(ctx, DHCP_RentIP_FullMethodName, in, out, cOpts...)
|
||||
err := c.cc.Invoke(ctx, DHCP_RentIP_FullMethodName, in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -50,9 +49,8 @@ func (c *dHCPClient) RentIP(ctx context.Context, in *RentIPRequest, opts ...grpc
|
||||
}
|
||||
|
||||
func (c *dHCPClient) ReleaseIP(ctx context.Context, in *ReleaseIPRequest, opts ...grpc.CallOption) (*ReleaseIPResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ReleaseIPResponse)
|
||||
err := c.cc.Invoke(ctx, DHCP_ReleaseIP_FullMethodName, in, out, cOpts...)
|
||||
err := c.cc.Invoke(ctx, DHCP_ReleaseIP_FullMethodName, in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -61,19 +59,16 @@ func (c *dHCPClient) ReleaseIP(ctx context.Context, in *ReleaseIPRequest, opts .
|
||||
|
||||
// DHCPServer is the server API for DHCP service.
|
||||
// All implementations must embed UnimplementedDHCPServer
|
||||
// for forward compatibility.
|
||||
// for forward compatibility
|
||||
type DHCPServer interface {
|
||||
RentIP(context.Context, *RentIPRequest) (*RentIPResponse, error)
|
||||
ReleaseIP(context.Context, *ReleaseIPRequest) (*ReleaseIPResponse, error)
|
||||
mustEmbedUnimplementedDHCPServer()
|
||||
}
|
||||
|
||||
// UnimplementedDHCPServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedDHCPServer struct{}
|
||||
// UnimplementedDHCPServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedDHCPServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedDHCPServer) RentIP(context.Context, *RentIPRequest) (*RentIPResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RentIP not implemented")
|
||||
@@ -82,7 +77,6 @@ func (UnimplementedDHCPServer) ReleaseIP(context.Context, *ReleaseIPRequest) (*R
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ReleaseIP not implemented")
|
||||
}
|
||||
func (UnimplementedDHCPServer) mustEmbedUnimplementedDHCPServer() {}
|
||||
func (UnimplementedDHCPServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeDHCPServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to DHCPServer will
|
||||
@@ -92,13 +86,6 @@ type UnsafeDHCPServer interface {
|
||||
}
|
||||
|
||||
func RegisterDHCPServer(s grpc.ServiceRegistrar, srv DHCPServer) {
|
||||
// If the following call pancis, it indicates UnimplementedDHCPServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&DHCP_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
|
@@ -6,13 +6,10 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/distribution/reference"
|
||||
"github.com/google/uuid"
|
||||
libconfig "github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/netutil"
|
||||
@@ -23,11 +20,9 @@ import (
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/client-go/util/retry"
|
||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||
"k8s.io/kubectl/pkg/cmd/util/podcmd"
|
||||
@@ -37,7 +32,6 @@ import (
|
||||
"k8s.io/utils/ptr"
|
||||
|
||||
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
|
||||
"github.com/wencaiwulue/kubevpn/v2/pkg/inject"
|
||||
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
|
||||
"github.com/wencaiwulue/kubevpn/v2/pkg/syncthing"
|
||||
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
|
||||
@@ -50,25 +44,14 @@ type CloneOptions struct {
|
||||
ExtraRouteInfo ExtraRouteInfo
|
||||
Engine config.Engine
|
||||
|
||||
TargetKubeconfig string
|
||||
TargetNamespace string
|
||||
TargetContainer string
|
||||
TargetImage string
|
||||
TargetRegistry string
|
||||
IsChangeTargetRegistry bool
|
||||
TargetWorkloadNames map[string]string
|
||||
|
||||
isSame bool
|
||||
TargetContainer string
|
||||
TargetImage string
|
||||
TargetWorkloadNames map[string]string
|
||||
|
||||
OriginKubeconfigPath string
|
||||
LocalDir string
|
||||
RemoteDir string
|
||||
|
||||
targetClientset *kubernetes.Clientset
|
||||
targetRestclient *rest.RESTClient
|
||||
targetConfig *rest.Config
|
||||
targetFactory cmdutil.Factory
|
||||
|
||||
clientset *kubernetes.Clientset
|
||||
restclient *rest.RESTClient
|
||||
config *rest.Config
|
||||
@@ -93,31 +76,6 @@ func (d *CloneOptions) InitClient(f cmdutil.Factory) (err error) {
|
||||
if d.Namespace, _, err = d.factory.ToRawKubeConfigLoader().Namespace(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// init target info
|
||||
if len(d.TargetKubeconfig) == 0 {
|
||||
d.TargetKubeconfig = d.OriginKubeconfigPath
|
||||
d.targetFactory = d.factory
|
||||
d.targetClientset = d.clientset
|
||||
d.targetConfig = d.config
|
||||
d.targetRestclient = d.restclient
|
||||
if len(d.TargetNamespace) == 0 {
|
||||
d.TargetNamespace = d.Namespace
|
||||
d.isSame = true
|
||||
}
|
||||
return
|
||||
}
|
||||
configFlags := genericclioptions.NewConfigFlags(true)
|
||||
configFlags.KubeConfig = pointer.String(d.TargetKubeconfig)
|
||||
configFlags.Namespace = pointer.String(d.TargetNamespace)
|
||||
matchVersionFlags := cmdutil.NewMatchVersionFlags(configFlags)
|
||||
d.targetFactory = cmdutil.NewFactory(matchVersionFlags)
|
||||
var found bool
|
||||
d.TargetNamespace, found, err = d.targetFactory.ToRawKubeConfigLoader().Namespace()
|
||||
if err != nil || !found {
|
||||
d.TargetNamespace = d.Namespace
|
||||
}
|
||||
d.targetClientset, err = d.targetFactory.KubernetesClientSet()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -147,7 +105,6 @@ func (d *CloneOptions) DoClone(ctx context.Context, kubeconfigJsonBytes []byte)
|
||||
if err = unstructured.SetNestedField(u.UnstructuredContent(), int64(1), "spec", "replicas"); err != nil {
|
||||
plog.G(ctx).Warnf("Failed to set repilcaset to 1: %v", err)
|
||||
}
|
||||
u.SetNamespace(d.TargetNamespace)
|
||||
RemoveUselessInfo(u)
|
||||
var newUUID uuid.UUID
|
||||
newUUID, err = uuid.NewUUID()
|
||||
@@ -156,17 +113,7 @@ func (d *CloneOptions) DoClone(ctx context.Context, kubeconfigJsonBytes []byte)
|
||||
}
|
||||
originName := u.GetName()
|
||||
u.SetName(fmt.Sprintf("%s-clone-%s", u.GetName(), newUUID.String()[:5]))
|
||||
d.TargetWorkloadNames[workload] = u.GetName()
|
||||
// if is another cluster, needs to set volume and set env
|
||||
if !d.isSame {
|
||||
if err = d.setVolume(u); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = d.setEnv(u); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
d.TargetWorkloadNames[workload] = fmt.Sprintf("%s/%s", object.Mapping.Resource.GroupResource().Resource, u.GetName())
|
||||
labelsMap := map[string]string{
|
||||
config.ManageBy: config.ConfigMapPodTrafficManager,
|
||||
"owner-ref": u.GetName(),
|
||||
@@ -185,7 +132,7 @@ func (d *CloneOptions) DoClone(ctx context.Context, kubeconfigJsonBytes []byte)
|
||||
return err
|
||||
}
|
||||
var client dynamic.Interface
|
||||
client, err = d.targetFactory.DynamicClient()
|
||||
client, err = d.factory.DynamicClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -282,104 +229,8 @@ func (d *CloneOptions) DoClone(ctx context.Context, kubeconfigJsonBytes []byte)
|
||||
Value: "1",
|
||||
},
|
||||
}...)*/
|
||||
container := &v1.Container{
|
||||
Name: config.ContainerSidecarVPN,
|
||||
Image: config.Image,
|
||||
// https://stackoverflow.com/questions/32918849/what-process-signal-does-pod-receive-when-executing-kubectl-rolling-update
|
||||
Command: append([]string{
|
||||
"kubevpn",
|
||||
"proxy",
|
||||
workload,
|
||||
"--kubeconfig", "/tmp/.kube/" + config.KUBECONFIG,
|
||||
"--namespace", d.Namespace,
|
||||
"--image", config.Image,
|
||||
"--netstack", string(d.Engine),
|
||||
"--foreground",
|
||||
}, args...),
|
||||
Env: []v1.EnvVar{},
|
||||
Resources: v1.ResourceRequirements{
|
||||
Requests: map[v1.ResourceName]resource.Quantity{
|
||||
v1.ResourceCPU: resource.MustParse("1000m"),
|
||||
v1.ResourceMemory: resource.MustParse("1024Mi"),
|
||||
},
|
||||
Limits: map[v1.ResourceName]resource.Quantity{
|
||||
v1.ResourceCPU: resource.MustParse("2000m"),
|
||||
v1.ResourceMemory: resource.MustParse("2048Mi"),
|
||||
},
|
||||
},
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
Name: config.KUBECONFIG,
|
||||
ReadOnly: false,
|
||||
MountPath: "/tmp/.kube",
|
||||
},
|
||||
},
|
||||
Lifecycle: &v1.Lifecycle{
|
||||
PostStart: &v1.LifecycleHandler{
|
||||
Exec: &v1.ExecAction{
|
||||
Command: []string{
|
||||
"/bin/bash",
|
||||
"-c",
|
||||
`
|
||||
echo 1 > /proc/sys/net/ipv4/ip_forward
|
||||
echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6
|
||||
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
|
||||
echo 1 > /proc/sys/net/ipv4/conf/all/route_localnet
|
||||
update-alternatives --set iptables /usr/sbin/iptables-legacy`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ImagePullPolicy: v1.PullIfNotPresent,
|
||||
SecurityContext: &v1.SecurityContext{
|
||||
Capabilities: &v1.Capabilities{
|
||||
Add: []v1.Capability{
|
||||
"NET_ADMIN",
|
||||
},
|
||||
},
|
||||
RunAsUser: pointer.Int64(0),
|
||||
RunAsGroup: pointer.Int64(0),
|
||||
Privileged: pointer.Bool(true),
|
||||
},
|
||||
}
|
||||
containerSync := &v1.Container{
|
||||
Name: config.ContainerSidecarSyncthing,
|
||||
Image: config.Image,
|
||||
// https://stackoverflow.com/questions/32918849/what-process-signal-does-pod-receive-when-executing-kubectl-rolling-update
|
||||
Command: []string{
|
||||
"kubevpn",
|
||||
"syncthing",
|
||||
"--dir",
|
||||
d.RemoteDir,
|
||||
},
|
||||
Resources: v1.ResourceRequirements{
|
||||
Requests: map[v1.ResourceName]resource.Quantity{
|
||||
v1.ResourceCPU: resource.MustParse("500m"),
|
||||
v1.ResourceMemory: resource.MustParse("512Mi"),
|
||||
},
|
||||
Limits: map[v1.ResourceName]resource.Quantity{
|
||||
v1.ResourceCPU: resource.MustParse("1000m"),
|
||||
v1.ResourceMemory: resource.MustParse("1024Mi"),
|
||||
},
|
||||
},
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
Name: syncDataDirName,
|
||||
ReadOnly: false,
|
||||
MountPath: d.RemoteDir,
|
||||
},
|
||||
},
|
||||
// only for:
|
||||
// panic: mkdir /.kubevpn: permission denied │
|
||||
// │
|
||||
// goroutine 1 [running]: │
|
||||
// github.com/wencaiwulue/kubevpn/v2/pkg/config.init.1() │
|
||||
// /go/src/github.com/wencaiwulue/kubevpn/pkg/config/const.go:34 +0x1ae
|
||||
SecurityContext: &v1.SecurityContext{
|
||||
RunAsUser: ptr.To[int64](0),
|
||||
RunAsGroup: ptr.To[int64](0),
|
||||
},
|
||||
}
|
||||
container := genVPNContainer(workload, d.Engine, d.Namespace, args)
|
||||
containerSync := genSyncthingContainer(d.RemoteDir, syncDataDirName)
|
||||
spec.Spec.Containers = append(containers, *container, *containerSync)
|
||||
//set spec
|
||||
marshal, err := json.Marshal(spec)
|
||||
@@ -397,11 +248,8 @@ update-alternatives --set iptables /usr/sbin/iptables-legacy`,
|
||||
if err = unstructured.SetNestedField(u.Object, m, path...); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = d.replaceRegistry(ctx, u); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, createErr := client.Resource(object.Mapping.Resource).Namespace(d.TargetNamespace).Create(context.Background(), u, metav1.CreateOptions{})
|
||||
_, createErr := client.Resource(object.Mapping.Resource).Namespace(d.Namespace).Create(context.Background(), u, metav1.CreateOptions{})
|
||||
//_, createErr := runtimeresource.NewHelper(object.Client, object.Mapping).Create(d.TargetNamespace, true, u)
|
||||
return createErr
|
||||
})
|
||||
@@ -411,7 +259,7 @@ update-alternatives --set iptables /usr/sbin/iptables-legacy`,
|
||||
plog.G(ctx).Infof("Create clone resource %s/%s in target cluster", u.GetObjectKind().GroupVersionKind().GroupKind().String(), u.GetName())
|
||||
plog.G(ctx).Infof("Wait for clone resource %s/%s to be ready", u.GetObjectKind().GroupVersionKind().GroupKind().String(), u.GetName())
|
||||
plog.G(ctx).Infoln()
|
||||
err = util.WaitPodToBeReady(ctx, d.targetClientset.CoreV1().Pods(d.TargetNamespace), metav1.LabelSelector{MatchLabels: labelsMap})
|
||||
err = util.WaitPodToBeReady(ctx, d.clientset.CoreV1().Pods(d.Namespace), metav1.LabelSelector{MatchLabels: labelsMap})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -427,8 +275,114 @@ update-alternatives --set iptables /usr/sbin/iptables-legacy`,
|
||||
return nil
|
||||
}
|
||||
|
||||
func genSyncthingContainer(remoteDir string, syncDataDirName string) *v1.Container {
|
||||
containerSync := &v1.Container{
|
||||
Name: config.ContainerSidecarSyncthing,
|
||||
Image: config.Image,
|
||||
// https://stackoverflow.com/questions/32918849/what-process-signal-does-pod-receive-when-executing-kubectl-rolling-update
|
||||
Command: []string{
|
||||
"kubevpn",
|
||||
"syncthing",
|
||||
"--dir",
|
||||
remoteDir,
|
||||
},
|
||||
Resources: v1.ResourceRequirements{
|
||||
Requests: map[v1.ResourceName]resource.Quantity{
|
||||
v1.ResourceCPU: resource.MustParse("500m"),
|
||||
v1.ResourceMemory: resource.MustParse("512Mi"),
|
||||
},
|
||||
Limits: map[v1.ResourceName]resource.Quantity{
|
||||
v1.ResourceCPU: resource.MustParse("1000m"),
|
||||
v1.ResourceMemory: resource.MustParse("1024Mi"),
|
||||
},
|
||||
},
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
Name: syncDataDirName,
|
||||
ReadOnly: false,
|
||||
MountPath: remoteDir,
|
||||
},
|
||||
},
|
||||
// only for:
|
||||
// panic: mkdir /.kubevpn: permission denied │
|
||||
// │
|
||||
// goroutine 1 [running]: │
|
||||
// github.com/wencaiwulue/kubevpn/v2/pkg/config.init.1() │
|
||||
// /go/src/github.com/wencaiwulue/kubevpn/pkg/config/const.go:34 +0x1ae
|
||||
SecurityContext: &v1.SecurityContext{
|
||||
RunAsUser: ptr.To[int64](0),
|
||||
RunAsGroup: ptr.To[int64](0),
|
||||
},
|
||||
}
|
||||
return containerSync
|
||||
}
|
||||
|
||||
func genVPNContainer(workload string, engine config.Engine, namespace string, args []string) *v1.Container {
|
||||
container := &v1.Container{
|
||||
Name: config.ContainerSidecarVPN,
|
||||
Image: config.Image,
|
||||
// https://stackoverflow.com/questions/32918849/what-process-signal-does-pod-receive-when-executing-kubectl-rolling-update
|
||||
Command: append([]string{
|
||||
"kubevpn",
|
||||
"proxy",
|
||||
workload,
|
||||
"--kubeconfig", "/tmp/.kube/" + config.KUBECONFIG,
|
||||
"--namespace", namespace,
|
||||
"--image", config.Image,
|
||||
"--netstack", string(engine),
|
||||
"--foreground",
|
||||
}, args...),
|
||||
Env: []v1.EnvVar{},
|
||||
Resources: v1.ResourceRequirements{
|
||||
Requests: map[v1.ResourceName]resource.Quantity{
|
||||
v1.ResourceCPU: resource.MustParse("1000m"),
|
||||
v1.ResourceMemory: resource.MustParse("1024Mi"),
|
||||
},
|
||||
Limits: map[v1.ResourceName]resource.Quantity{
|
||||
v1.ResourceCPU: resource.MustParse("2000m"),
|
||||
v1.ResourceMemory: resource.MustParse("2048Mi"),
|
||||
},
|
||||
},
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
Name: config.KUBECONFIG,
|
||||
ReadOnly: false,
|
||||
MountPath: "/tmp/.kube",
|
||||
},
|
||||
},
|
||||
Lifecycle: &v1.Lifecycle{
|
||||
PostStart: &v1.LifecycleHandler{
|
||||
Exec: &v1.ExecAction{
|
||||
Command: []string{
|
||||
"/bin/bash",
|
||||
"-c",
|
||||
`
|
||||
echo 1 > /proc/sys/net/ipv4/ip_forward
|
||||
echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6
|
||||
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
|
||||
echo 1 > /proc/sys/net/ipv4/conf/all/route_localnet
|
||||
update-alternatives --set iptables /usr/sbin/iptables-legacy`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ImagePullPolicy: v1.PullIfNotPresent,
|
||||
SecurityContext: &v1.SecurityContext{
|
||||
Capabilities: &v1.Capabilities{
|
||||
Add: []v1.Capability{
|
||||
"NET_ADMIN",
|
||||
},
|
||||
},
|
||||
RunAsUser: pointer.Int64(0),
|
||||
RunAsGroup: pointer.Int64(0),
|
||||
Privileged: pointer.Bool(true),
|
||||
},
|
||||
}
|
||||
return container
|
||||
}
|
||||
|
||||
func (d *CloneOptions) SyncDir(ctx context.Context, labels string) error {
|
||||
list, err := util.GetRunningPodList(ctx, d.targetClientset, d.TargetNamespace, labels)
|
||||
list, err := util.GetRunningPodList(ctx, d.clientset, d.Namespace, labels)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -449,8 +403,8 @@ func (d *CloneOptions) SyncDir(ctx context.Context, labels string) error {
|
||||
defer time.Sleep(time.Second * 2)
|
||||
|
||||
sortBy := func(pods []*v1.Pod) sort.Interface { return sort.Reverse(podutils.ActivePods(pods)) }
|
||||
_, _, _ = polymorphichelpers.GetFirstPod(d.targetClientset.CoreV1(), d.TargetNamespace, labels, time.Second*30, sortBy)
|
||||
list, err := util.GetRunningPodList(d.ctx, d.targetClientset, d.TargetNamespace, labels)
|
||||
_, _, _ = polymorphichelpers.GetFirstPod(d.clientset.CoreV1(), d.Namespace, labels, time.Second*30, sortBy)
|
||||
list, err := util.GetRunningPodList(d.ctx, d.clientset, d.Namespace, labels)
|
||||
if err != nil {
|
||||
plog.G(ctx).Error(err)
|
||||
return
|
||||
@@ -505,393 +459,31 @@ func RemoveUselessInfo(u *unstructured.Unstructured) {
|
||||
u.SetAnnotations(a)
|
||||
}
|
||||
|
||||
// setVolume
|
||||
/*
|
||||
1) calculate volume content, and download it into emptyDir
|
||||
*/
|
||||
func (d *CloneOptions) setVolume(u *unstructured.Unstructured) error {
|
||||
|
||||
const TokenVolumeMountPath = "/var/run/secrets/kubernetes.io/serviceaccount"
|
||||
|
||||
type VolumeMountContainerPair struct {
|
||||
container v1.Container
|
||||
volumeMount v1.VolumeMount
|
||||
}
|
||||
temp, path, err := util.GetPodTemplateSpecPath(u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
lab := labels.SelectorFromSet(temp.Labels).String()
|
||||
var list []v1.Pod
|
||||
list, err = util.GetRunningPodList(context.Background(), d.clientset, d.Namespace, lab)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pod := list[0]
|
||||
|
||||
// remove serviceAccount info
|
||||
temp.Spec.ServiceAccountName = ""
|
||||
temp.Spec.AutomountServiceAccountToken = pointer.Bool(false)
|
||||
|
||||
var volumeMap = make(map[string]v1.Volume)
|
||||
var volumeList []v1.Volume
|
||||
// pod's volume maybe more than spec defined
|
||||
for _, volume := range pod.Spec.Volumes {
|
||||
volumeMap[volume.Name] = volume
|
||||
|
||||
// keep volume emptyDir
|
||||
if volume.EmptyDir != nil {
|
||||
volumeList = append(volumeList, volume)
|
||||
} else {
|
||||
volumeList = append(volumeList, v1.Volume{
|
||||
Name: volume.Name,
|
||||
VolumeSource: v1.VolumeSource{
|
||||
EmptyDir: &v1.EmptyDirVolumeSource{},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var tokenVolume string
|
||||
var volumeM = make(map[string][]VolumeMountContainerPair)
|
||||
for _, container := range pod.Spec.Containers {
|
||||
// group by volume name, what we want is figure out what's contains in every volume
|
||||
// we need to restore a total volume base on mountPath and subPath
|
||||
for _, volumeMount := range container.VolumeMounts {
|
||||
if volumeMap[volumeMount.Name].EmptyDir != nil {
|
||||
continue
|
||||
}
|
||||
if volumeMount.MountPath == TokenVolumeMountPath {
|
||||
tokenVolume = volumeMount.Name
|
||||
}
|
||||
mounts := volumeM[volumeMount.Name]
|
||||
if mounts == nil {
|
||||
volumeM[volumeMount.Name] = []VolumeMountContainerPair{}
|
||||
}
|
||||
volumeM[volumeMount.Name] = append(volumeM[volumeMount.Name], VolumeMountContainerPair{
|
||||
container: container,
|
||||
volumeMount: volumeMount,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var initContainer []v1.Container
|
||||
for _, volume := range pod.Spec.Volumes {
|
||||
mountPoint := "/tmp/" + volume.Name
|
||||
var args []string
|
||||
for _, pair := range volumeM[volume.Name] {
|
||||
remote := filepath.Join(pair.volumeMount.MountPath, pair.volumeMount.SubPath)
|
||||
local := filepath.Join(mountPoint, pair.volumeMount.SubPath)
|
||||
// kubectl cp <some-namespace>/<some-pod>:/tmp/foo /tmp/bar
|
||||
args = append(args,
|
||||
fmt.Sprintf("kubevpn cp %s/%s:%s %s -c %s", pod.Namespace, pod.Name, remote, local, pair.container.Name),
|
||||
)
|
||||
}
|
||||
// means maybe volume only used in initContainers
|
||||
if len(args) == 0 {
|
||||
for i := 0; i < len(temp.Spec.InitContainers); i++ {
|
||||
for _, mount := range temp.Spec.InitContainers[i].VolumeMounts {
|
||||
if mount.Name == volume.Name {
|
||||
// remove useless initContainer
|
||||
temp.Spec.InitContainers = append(temp.Spec.InitContainers[:i], temp.Spec.InitContainers[i+1:]...)
|
||||
i--
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
newContainer := v1.Container{
|
||||
Name: fmt.Sprintf("download-%s", volume.Name),
|
||||
Image: config.Image,
|
||||
Command: []string{"sh", "-c"},
|
||||
Args: []string{strings.Join(args, "&&")},
|
||||
WorkingDir: "/tmp",
|
||||
Env: []v1.EnvVar{
|
||||
{
|
||||
Name: clientcmd.RecommendedConfigPathEnvVar,
|
||||
Value: "/tmp/.kube/kubeconfig",
|
||||
},
|
||||
},
|
||||
Resources: v1.ResourceRequirements{},
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
Name: volume.Name,
|
||||
MountPath: mountPoint,
|
||||
},
|
||||
{
|
||||
Name: config.KUBECONFIG,
|
||||
ReadOnly: false,
|
||||
MountPath: "/tmp/.kube",
|
||||
},
|
||||
},
|
||||
ImagePullPolicy: v1.PullIfNotPresent,
|
||||
}
|
||||
initContainer = append(initContainer, newContainer)
|
||||
}
|
||||
// put download volume to front
|
||||
temp.Spec.InitContainers = append(initContainer, temp.Spec.InitContainers...)
|
||||
// replace old one
|
||||
temp.Spec.Volumes = volumeList
|
||||
// remove containers vpn and envoy-proxy
|
||||
inject.RemoveContainers(temp)
|
||||
// add each container service account token
|
||||
if tokenVolume != "" {
|
||||
for i := 0; i < len(temp.Spec.Containers); i++ {
|
||||
var found bool
|
||||
for _, mount := range temp.Spec.Containers[i].VolumeMounts {
|
||||
if mount.MountPath == TokenVolumeMountPath {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
temp.Spec.Containers[i].VolumeMounts = append(temp.Spec.Containers[i].VolumeMounts, v1.VolumeMount{
|
||||
Name: tokenVolume,
|
||||
MountPath: TokenVolumeMountPath,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
var marshal []byte
|
||||
if marshal, err = json.Marshal(temp.Spec); err != nil {
|
||||
return err
|
||||
}
|
||||
var content map[string]interface{}
|
||||
if err = json.Unmarshal(marshal, &content); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = unstructured.SetNestedField(u.Object, content, append(path, "spec")...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *CloneOptions) setEnv(u *unstructured.Unstructured) error {
|
||||
temp, path, err := util.GetPodTemplateSpecPath(u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
/*sortBy := func(pods []*v1.Pod) sort.Interface {
|
||||
for i := 0; i < len(pods); i++ {
|
||||
if pods[i].DeletionTimestamp != nil {
|
||||
pods = append(pods[:i], pods[i+1:]...)
|
||||
i--
|
||||
}
|
||||
}
|
||||
return sort.Reverse(podutils.ActivePods(pods))
|
||||
}
|
||||
lab := labels.SelectorFromSet(temp.Labels).String()
|
||||
pod, _, err := polymorphichelpers.GetFirstPod(d.clientset.CoreV1(), d.Namespace, lab, time.Second*60, sortBy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var envMap map[string][]string
|
||||
envMap, err = util.GetEnv(context.Background(), d.factory, d.Namespace, pod.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}*/
|
||||
|
||||
var secretMap = make(map[string]*v1.Secret)
|
||||
var configmapMap = make(map[string]*v1.ConfigMap)
|
||||
|
||||
var howToGetCm = func(name string) {
|
||||
if configmapMap[name] == nil {
|
||||
cm, err := d.clientset.CoreV1().ConfigMaps(d.Namespace).Get(context.Background(), name, metav1.GetOptions{})
|
||||
if err == nil {
|
||||
configmapMap[name] = cm
|
||||
}
|
||||
}
|
||||
}
|
||||
var howToGetSecret = func(name string) {
|
||||
if configmapMap[name] == nil {
|
||||
secret, err := d.clientset.CoreV1().Secrets(d.Namespace).Get(context.Background(), name, metav1.GetOptions{})
|
||||
if err == nil {
|
||||
secretMap[name] = secret
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get all ref configmaps and secrets
|
||||
for _, container := range temp.Spec.Containers {
|
||||
for _, envVar := range container.Env {
|
||||
if envVar.ValueFrom != nil {
|
||||
if ref := envVar.ValueFrom.ConfigMapKeyRef; ref != nil {
|
||||
howToGetCm(ref.Name)
|
||||
}
|
||||
if ref := envVar.ValueFrom.SecretKeyRef; ref != nil {
|
||||
howToGetSecret(ref.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, source := range container.EnvFrom {
|
||||
if ref := source.ConfigMapRef; ref != nil {
|
||||
if configmapMap[ref.Name] == nil {
|
||||
howToGetCm(ref.Name)
|
||||
}
|
||||
}
|
||||
if ref := source.SecretRef; ref != nil {
|
||||
howToGetSecret(ref.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parse real value from secrets and configmaps
|
||||
for i := 0; i < len(temp.Spec.Containers); i++ {
|
||||
container := temp.Spec.Containers[i]
|
||||
var envVars []v1.EnvVar
|
||||
for _, envFromSource := range container.EnvFrom {
|
||||
if ref := envFromSource.ConfigMapRef; ref != nil && configmapMap[ref.Name] != nil {
|
||||
cm := configmapMap[ref.Name]
|
||||
for k, v := range cm.Data {
|
||||
if strings.HasPrefix(k, envFromSource.Prefix) {
|
||||
envVars = append(envVars, v1.EnvVar{
|
||||
Name: k,
|
||||
Value: v,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
if ref := envFromSource.SecretRef; ref != nil && secretMap[ref.Name] != nil {
|
||||
secret := secretMap[ref.Name]
|
||||
for k, v := range secret.Data {
|
||||
if strings.HasPrefix(k, envFromSource.Prefix) {
|
||||
envVars = append(envVars, v1.EnvVar{
|
||||
Name: k,
|
||||
Value: string(v),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
temp.Spec.Containers[i].EnvFrom = nil
|
||||
temp.Spec.Containers[i].Env = append(temp.Spec.Containers[i].Env, envVars...)
|
||||
|
||||
for j, envVar := range container.Env {
|
||||
if envVar.ValueFrom != nil {
|
||||
if ref := envVar.ValueFrom.ConfigMapKeyRef; ref != nil {
|
||||
if configMap := configmapMap[ref.Name]; configMap != nil {
|
||||
temp.Spec.Containers[i].Env[j].Value = configMap.Data[ref.Key]
|
||||
temp.Spec.Containers[i].Env[j].ValueFrom = nil
|
||||
}
|
||||
}
|
||||
if ref := envVar.ValueFrom.SecretKeyRef; ref != nil {
|
||||
if secret := secretMap[ref.Name]; secret != nil {
|
||||
temp.Spec.Containers[i].Env[j].Value = string(secret.Data[ref.Key])
|
||||
temp.Spec.Containers[i].Env[j].ValueFrom = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var marshal []byte
|
||||
if marshal, err = json.Marshal(temp.Spec); err != nil {
|
||||
return err
|
||||
}
|
||||
var content map[string]interface{}
|
||||
if err = json.Unmarshal(marshal, &content); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = unstructured.SetNestedField(u.Object, content, append(path, "spec")...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// replace origin registry with special registry for pulling image
|
||||
func (d *CloneOptions) replaceRegistry(ctx context.Context, u *unstructured.Unstructured) error {
|
||||
// not pass this options, do nothing
|
||||
if !d.IsChangeTargetRegistry {
|
||||
return nil
|
||||
}
|
||||
|
||||
temp, path, err := util.GetPodTemplateSpecPath(u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i, container := range temp.Spec.InitContainers {
|
||||
oldImage := container.Image
|
||||
named, err := reference.ParseNormalizedNamed(oldImage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
domain := reference.Domain(named)
|
||||
newImage := strings.TrimPrefix(strings.ReplaceAll(oldImage, domain, d.TargetRegistry), "/")
|
||||
temp.Spec.InitContainers[i].Image = newImage
|
||||
plog.G(ctx).Debugf("Update init container: %s image: %s --> %s", container.Name, oldImage, newImage)
|
||||
}
|
||||
|
||||
for i, container := range temp.Spec.Containers {
|
||||
oldImage := container.Image
|
||||
named, err := reference.ParseNormalizedNamed(oldImage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
domain := reference.Domain(named)
|
||||
newImage := strings.TrimPrefix(strings.ReplaceAll(oldImage, domain, d.TargetRegistry), "/")
|
||||
temp.Spec.Containers[i].Image = newImage
|
||||
plog.G(ctx).Debugf("Update container: %s image: %s --> %s", container.Name, oldImage, newImage)
|
||||
}
|
||||
|
||||
var marshal []byte
|
||||
if marshal, err = json.Marshal(temp.Spec); err != nil {
|
||||
return err
|
||||
}
|
||||
var content map[string]interface{}
|
||||
if err = json.Unmarshal(marshal, &content); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = unstructured.SetNestedField(u.Object, content, append(path, "spec")...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *CloneOptions) Cleanup(ctx context.Context, workloads ...string) error {
|
||||
if len(workloads) == 0 {
|
||||
workloads = d.Workloads
|
||||
for _, v := range d.TargetWorkloadNames {
|
||||
workloads = append(workloads, v)
|
||||
}
|
||||
}
|
||||
for _, workload := range workloads {
|
||||
plog.G(ctx).Infof("Cleaning up clone workload: %s", workload)
|
||||
object, err := util.GetUnstructuredObject(d.factory, d.Namespace, workload)
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to get unstructured object error: %s", err.Error())
|
||||
return err
|
||||
}
|
||||
labelsMap := map[string]string{
|
||||
config.ManageBy: config.ConfigMapPodTrafficManager,
|
||||
"origin-workload": object.Name,
|
||||
}
|
||||
selector := labels.SelectorFromSet(labelsMap)
|
||||
controller, err := util.GetTopOwnerReferenceBySelector(d.targetFactory, d.TargetNamespace, selector.String())
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to get controller error: %s", err.Error())
|
||||
plog.G(ctx).Errorf("Failed to get unstructured object: %s", err)
|
||||
return err
|
||||
}
|
||||
var client dynamic.Interface
|
||||
client, err = d.targetFactory.DynamicClient()
|
||||
client, err = d.factory.DynamicClient()
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to get dynamic client error: %s", err.Error())
|
||||
plog.G(ctx).Errorf("Failed to get dynamic client: %v", err)
|
||||
return err
|
||||
}
|
||||
for _, cloneName := range controller.UnsortedList() {
|
||||
split := strings.Split(cloneName, "/")
|
||||
if len(split) == 2 {
|
||||
cloneName = split[1]
|
||||
}
|
||||
err = client.Resource(object.Mapping.Resource).Namespace(d.TargetNamespace).Delete(context.Background(), cloneName, metav1.DeleteOptions{})
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
plog.G(ctx).Errorf("Failed to delete clone object: %v", err)
|
||||
return err
|
||||
}
|
||||
plog.G(ctx).Infof("Deleted clone object: %s", cloneName)
|
||||
err = client.Resource(object.Mapping.Resource).Namespace(d.Namespace).Delete(context.Background(), object.Name, metav1.DeleteOptions{})
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
plog.G(ctx).Errorf("Failed to delete clone object: %v", err)
|
||||
return err
|
||||
}
|
||||
plog.G(ctx).Debugf("Cleanup clone workload: %s successfully", workload)
|
||||
plog.G(ctx).Infof("Deleted clone object: %s/%s", object.Mapping.Resource.GroupResource().Resource, object.Name)
|
||||
}
|
||||
for _, f := range d.rollbackFuncList {
|
||||
if f != nil {
|
||||
|
Reference in New Issue
Block a user