diff --git a/Gopkg.lock b/Gopkg.lock index ee42a9d48558a..2eec8a7fec778 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -298,6 +298,12 @@ revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" version = "v0.0.3" +[[projects]] + name = "github.com/pborman/uuid" + packages = ["."] + revision = "e790cca94e6cc75c7064b1332e63811d4aae1a53" + version = "v1.1" + [[projects]] branch = "master" name = "github.com/petar/GoLLRB" @@ -618,6 +624,7 @@ "pkg/util/net", "pkg/util/runtime", "pkg/util/sets", + "pkg/util/uuid", "pkg/util/validation", "pkg/util/validation/field", "pkg/util/wait", @@ -753,6 +760,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "f1502665746a2148c56270e7a28dfbd393d56047b20dcee363c9e0202f651001" + inputs-digest = "683981f86c65c4c2871048e1305c2468fb7dea01ec6de3dbff52c932d8c2f803" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 3e9aa22b33d4c..19074d37dce35 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -39,3 +39,7 @@ required = [ [[constraint]] name = "github.com/ksonnet/ksonnet" branch = "master" + +[[constraint]] + name = "github.com/pborman/uuid" + version = "1.1.0" diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index 4b70e019e7b1e..e5f7017c21cb7 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -219,7 +219,7 @@ func NewApplicationRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra. conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) for _, appName := range args { - _, err := appIf.Delete(context.Background(), &application.ApplicationQuery{Name: appName}) + _, err := appIf.Delete(context.Background(), &application.DeleteApplicationRequest{Name: appName}) errors.CheckError(err) } }, diff --git a/common/common.go b/common/common.go index a0643abf7ddb5..cdebf67f30551 100644 --- a/common/common.go +++ b/common/common.go @@ -25,6 +25,8 @@ var ( // LabelKeyApplicationControllerInstanceID is the label which allows to separate application among multiple running application controllers. LabelKeyApplicationControllerInstanceID = application.ApplicationFullName + "/controller-instanceid" + // LabelApplicationName is the label which indicates that resource belongs to application with the specified name + LabelApplicationName = application.ApplicationFullName + "/app-name" ) // ArgoCDManagerServiceAccount is the name of the service account for managing a cluster diff --git a/controller/controller.go b/controller/controller.go index e48881990a3eb..996f7f118f20a 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -150,6 +150,7 @@ func (ctrl *ApplicationController) tryRefreshAppStatus(app *appv1.Application) ( Revision: revision, Path: app.Spec.Source.Path, Environment: app.Spec.Source.Environment, + AppLabel: app.Name, }) if err != nil { log.Errorf("Failed to load application manifest %v", err) @@ -166,7 +167,7 @@ func (ctrl *ApplicationController) tryRefreshAppStatus(app *appv1.Application) ( targetObjs[i] = &obj } - server, namespace := argoutil.ResolveServerNamespace(app, manifestInfo) + server, namespace := argoutil.ResolveServerNamespace(app.Spec.Destination, manifestInfo) comparisonResult, err := ctrl.appComparator.CompareAppState(server, namespace, targetObjs, app) if err != nil { return nil, err diff --git a/reposerver/repository/repository.go b/reposerver/repository/repository.go index 5e9d12f74df18..7bcac46dce3ae 100644 --- a/reposerver/repository/repository.go +++ b/reposerver/repository/repository.go @@ -1,17 +1,19 @@ package repository import ( + "encoding/json" + "fmt" + "io/ioutil" "os" + "os/exec" "path" "strings" - "fmt" - - "encoding/json" - + "github.com/argoproj/argo-cd/common" "github.com/argoproj/argo-cd/util" "github.com/argoproj/argo-cd/util/git" ksutil "github.com/argoproj/argo-cd/util/ksonnet" + log "github.com/sirupsen/logrus" "golang.org/x/net/context" "k8s.io/client-go/kubernetes" ) @@ -34,7 +36,24 @@ func NewService(namespace string, kubeClient kubernetes.Interface, gitClient git } } -// GenerateManifest generate a manifest for application in specified repo name and revision +func (s *Service) createTempRepo(appRepoPath string, appPath string, sourceEnv string, files map[string]string) (string, error) { + tmpRepoPath, err := ioutil.TempDir("", "") + if err != nil { + return "", err + } + _, err = exec.Command("cp", "-r", appRepoPath+"/", tmpRepoPath).Output() + if err != nil { + return "", err + } + for file, content := range files { + err = ioutil.WriteFile(path.Join(tmpRepoPath, appPath, "environments", sourceEnv, file), []byte(content), 0644) + if err != nil { + return "", err + } + } + return tmpRepoPath, nil +} + func (s *Service) GenerateManifest(c context.Context, q *ManifestRequest) (*ManifestResponse, error) { appRepoPath := path.Join(os.TempDir(), strings.Replace(q.Repo.Repo, "/", "_", -1)) s.repoLock.Lock(appRepoPath) @@ -50,6 +69,19 @@ func (s *Service) GenerateManifest(c context.Context, q *ManifestRequest) (*Mani return nil, err } appPath := path.Join(appRepoPath, q.Path) + if q.InputFiles != nil && len(q.InputFiles) > 0 { + tempRepoPath, err := s.createTempRepo(appRepoPath, q.Path, q.Environment, q.InputFiles) + if err != nil { + return nil, err + } + appPath = path.Join(tempRepoPath, q.Path) + defer func() { + err := os.RemoveAll(tempRepoPath) + if err != nil { + log.Warningf("Unable to cleanup temp directory: %v", err) + } + }() + } ksApp, err := ksutil.NewKsonnetApp(appPath) if err != nil { return nil, err @@ -66,6 +98,14 @@ func (s *Service) GenerateManifest(c context.Context, q *ManifestRequest) (*Mani } manifests := make([]string, len(targetObjs)) for i, target := range targetObjs { + if q.AppLabel != "" { + labels := target.GetLabels() + if labels == nil { + labels = make(map[string]string) + } + labels[common.LabelApplicationName] = q.AppLabel + target.SetLabels(labels) + } manifestStr, err := json.Marshal(target.Object) if err != nil { return nil, err diff --git a/reposerver/repository/repository.pb.go b/reposerver/repository/repository.pb.go index 5398b34a521df..3ba7018220c47 100644 --- a/reposerver/repository/repository.pb.go +++ b/reposerver/repository/repository.pb.go @@ -45,6 +45,8 @@ type ManifestRequest struct { Revision string `protobuf:"bytes,2,opt,name=revision" json:"revision,omitempty"` Path string `protobuf:"bytes,3,opt,name=path" json:"path,omitempty"` Environment string `protobuf:"bytes,4,opt,name=environment" json:"environment,omitempty"` + AppLabel string `protobuf:"bytes,5,opt,name=appLabel" json:"appLabel,omitempty"` + InputFiles map[string]string `protobuf:"bytes,6,rep,name=inputFiles" json:"inputFiles,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` } func (m *ManifestRequest) Reset() { *m = ManifestRequest{} } @@ -80,6 +82,20 @@ func (m *ManifestRequest) GetEnvironment() string { return "" } +func (m *ManifestRequest) GetAppLabel() string { + if m != nil { + return m.AppLabel + } + return "" +} + +func (m *ManifestRequest) GetInputFiles() map[string]string { + if m != nil { + return m.InputFiles + } + return nil +} + type ManifestResponse struct { Manifests []string `protobuf:"bytes,1,rep,name=manifests" json:"manifests,omitempty"` Namespace string `protobuf:"bytes,2,opt,name=namespace" json:"namespace,omitempty"` @@ -287,35 +303,38 @@ var _RepositoryService_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("reposerver/repository/repository.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 472 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x54, 0x41, 0x8f, 0xd3, 0x3c, - 0x10, 0xdd, 0x6c, 0xfb, 0x55, 0x5f, 0xa7, 0x48, 0x74, 0xad, 0x15, 0x8a, 0x42, 0x91, 0xaa, 0x1c, - 0x50, 0x39, 0x60, 0xab, 0xdd, 0xcb, 0xc2, 0x0d, 0xa4, 0x6a, 0xc5, 0x61, 0x05, 0x0a, 0x27, 0xb8, - 0x20, 0x6f, 0x3a, 0x9b, 0x9a, 0x36, 0xb6, 0xb1, 0xdd, 0x48, 0xfd, 0x19, 0xfc, 0x16, 0xee, 0xf0, - 0xd7, 0x50, 0x1c, 0xb7, 0x89, 0xd8, 0x65, 0xef, 0xdc, 0xde, 0xbc, 0x71, 0xe6, 0xcd, 0x3c, 0x8f, - 0x03, 0xcf, 0x0d, 0x6a, 0x65, 0xd1, 0x54, 0x68, 0x98, 0x87, 0xc2, 0x29, 0xb3, 0xef, 0x40, 0xaa, - 0x8d, 0x72, 0x8a, 0x40, 0xcb, 0x24, 0xe7, 0x85, 0x2a, 0x94, 0xa7, 0x59, 0x8d, 0x9a, 0x13, 0xc9, - 0xa4, 0x50, 0xaa, 0xd8, 0x22, 0xe3, 0x5a, 0x30, 0x2e, 0xa5, 0x72, 0xdc, 0x09, 0x25, 0x6d, 0xc8, - 0xa6, 0x9b, 0x4b, 0x4b, 0x85, 0xf2, 0xd9, 0x5c, 0x19, 0x64, 0xd5, 0x9c, 0x15, 0x28, 0xd1, 0x70, - 0x87, 0xab, 0x70, 0xe6, 0x5d, 0x21, 0xdc, 0x7a, 0x77, 0x43, 0x73, 0x55, 0x32, 0x6e, 0xbc, 0xc4, - 0x57, 0x0f, 0x5e, 0xe6, 0x2b, 0xa6, 0x37, 0x45, 0xfd, 0xb1, 0x65, 0x5c, 0xeb, 0xad, 0xc8, 0x7d, - 0x71, 0x56, 0xcd, 0xf9, 0x56, 0xaf, 0xf9, 0x9d, 0x52, 0xe9, 0xcf, 0x08, 0x1e, 0x5f, 0x73, 0x29, - 0x6e, 0xd1, 0xba, 0x0c, 0xbf, 0xed, 0xd0, 0x3a, 0xf2, 0x09, 0xfa, 0xf5, 0x10, 0x71, 0x34, 0x8d, - 0x66, 0xa3, 0xc5, 0x92, 0xb6, 0x6a, 0xf4, 0xa0, 0xe6, 0xc1, 0x97, 0x7c, 0x45, 0xf5, 0xa6, 0xa0, - 0xb5, 0x1a, 0xed, 0xa8, 0xd1, 0x83, 0x1a, 0xcd, 0x8e, 0x5e, 0x64, 0xbe, 0x24, 0x49, 0xe0, 0x7f, - 0x83, 0x95, 0xb0, 0x42, 0xc9, 0xf8, 0x74, 0x1a, 0xcd, 0x86, 0xd9, 0x31, 0x26, 0x04, 0xfa, 0x9a, - 0xbb, 0x75, 0xdc, 0xf3, 0xbc, 0xc7, 0x64, 0x0a, 0x23, 0x94, 0x95, 0x30, 0x4a, 0x96, 0x28, 0x5d, - 0xdc, 0xf7, 0xa9, 0x2e, 0x95, 0xde, 0xc2, 0xb8, 0xed, 0xdf, 0x6a, 0x25, 0x2d, 0x92, 0x09, 0x0c, - 0xcb, 0xc0, 0xd9, 0x38, 0x9a, 0xf6, 0x66, 0xc3, 0xac, 0x25, 0xea, 0xac, 0xe4, 0x25, 0x5a, 0xcd, - 0x73, 0x0c, 0x4d, 0xb4, 0x04, 0x79, 0x02, 0x83, 0xe6, 0x96, 0x43, 0x1f, 0x21, 0x4a, 0x7f, 0x45, - 0x30, 0x5e, 0xca, 0xea, 0x03, 0x37, 0xbc, 0xb4, 0xff, 0xa4, 0x53, 0xdf, 0x23, 0x38, 0xeb, 0x4c, - 0x10, 0xbc, 0x7a, 0x03, 0x03, 0xed, 0x19, 0x6f, 0xd4, 0x68, 0xf1, 0x82, 0x76, 0x56, 0xfa, 0xce, - 0x71, 0xda, 0x84, 0x4b, 0xe9, 0xcc, 0x3e, 0x0b, 0x1f, 0x26, 0xaf, 0x60, 0xd4, 0xa1, 0xc9, 0x18, - 0x7a, 0x1b, 0xdc, 0x7b, 0x4f, 0x86, 0x59, 0x0d, 0xc9, 0x39, 0xfc, 0x57, 0xf1, 0xed, 0xee, 0xe0, - 0x76, 0x13, 0xbc, 0x3e, 0xbd, 0x8c, 0x16, 0x3f, 0x22, 0x38, 0x6b, 0x47, 0xff, 0x88, 0xa6, 0x12, - 0x39, 0x92, 0xf7, 0x30, 0xbe, 0x0a, 0x7b, 0x7a, 0xb8, 0x5b, 0xf2, 0xb4, 0xdb, 0xd7, 0x1f, 0x1b, - 0x9b, 0x4c, 0xee, 0x4f, 0x36, 0x3d, 0xa7, 0x27, 0xe4, 0x1a, 0x1e, 0x5d, 0xa1, 0x3b, 0x4e, 0x43, - 0x26, 0x7f, 0x19, 0xb2, 0xa9, 0xf6, 0xec, 0x41, 0x0b, 0xd2, 0x93, 0xb7, 0x17, 0x9f, 0xe7, 0x0f, - 0xbd, 0xc0, 0x7b, 0xff, 0x14, 0x37, 0x03, 0xff, 0xe0, 0x2e, 0x7e, 0x07, 0x00, 0x00, 0xff, 0xff, - 0x31, 0x78, 0x89, 0x02, 0x49, 0x04, 0x00, 0x00, + // 527 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x54, 0xd1, 0x8a, 0xd3, 0x4c, + 0x14, 0xde, 0xb4, 0xdd, 0xf2, 0xf7, 0xf4, 0x87, 0xed, 0x0e, 0x8b, 0x84, 0x58, 0xa1, 0xe4, 0x42, + 0x2a, 0xe2, 0x84, 0x76, 0x6f, 0x56, 0xc1, 0x0b, 0x85, 0xba, 0x2c, 0xba, 0x28, 0xf1, 0x4a, 0x6f, + 0x64, 0x9a, 0x9e, 0x4d, 0xc7, 0xa6, 0x33, 0xe3, 0xcc, 0x34, 0xd0, 0xc7, 0xf0, 0x59, 0x7c, 0x00, + 0xdf, 0xc6, 0xe7, 0x90, 0x4c, 0xd2, 0x26, 0xec, 0xae, 0x05, 0x2f, 0xbd, 0x3b, 0xe7, 0x3b, 0x67, + 0xbe, 0x2f, 0xdf, 0x39, 0x93, 0x81, 0xc7, 0x1a, 0x95, 0x34, 0xa8, 0x73, 0xd4, 0x91, 0x0b, 0xb9, + 0x95, 0x7a, 0xdb, 0x08, 0xa9, 0xd2, 0xd2, 0x4a, 0x02, 0x35, 0x12, 0x9c, 0xa5, 0x32, 0x95, 0x0e, + 0x8e, 0x8a, 0xa8, 0xec, 0x08, 0x86, 0xa9, 0x94, 0x69, 0x86, 0x11, 0x53, 0x3c, 0x62, 0x42, 0x48, + 0xcb, 0x2c, 0x97, 0xc2, 0x54, 0xd5, 0x70, 0x75, 0x61, 0x28, 0x97, 0xae, 0x9a, 0x48, 0x8d, 0x51, + 0x3e, 0x89, 0x52, 0x14, 0xa8, 0x99, 0xc5, 0x45, 0xd5, 0x73, 0x95, 0x72, 0xbb, 0xdc, 0xcc, 0x69, + 0x22, 0xd7, 0x11, 0xd3, 0x4e, 0xe2, 0xab, 0x0b, 0x9e, 0x25, 0x8b, 0x48, 0xad, 0xd2, 0xe2, 0xb0, + 0x89, 0x98, 0x52, 0x19, 0x4f, 0x1c, 0x79, 0x94, 0x4f, 0x58, 0xa6, 0x96, 0xec, 0x0e, 0x55, 0xf8, + 0xab, 0x05, 0x27, 0xd7, 0x4c, 0xf0, 0x1b, 0x34, 0x36, 0xc6, 0x6f, 0x1b, 0x34, 0x96, 0x7c, 0x82, + 0x4e, 0x61, 0xc2, 0xf7, 0x46, 0xde, 0xb8, 0x3f, 0x9d, 0xd1, 0x5a, 0x8d, 0xee, 0xd4, 0x5c, 0xf0, + 0x25, 0x59, 0x50, 0xb5, 0x4a, 0x69, 0xa1, 0x46, 0x1b, 0x6a, 0x74, 0xa7, 0x46, 0xe3, 0xfd, 0x2c, + 0x62, 0x47, 0x49, 0x02, 0xf8, 0x4f, 0x63, 0xce, 0x0d, 0x97, 0xc2, 0x6f, 0x8d, 0xbc, 0x71, 0x2f, + 0xde, 0xe7, 0x84, 0x40, 0x47, 0x31, 0xbb, 0xf4, 0xdb, 0x0e, 0x77, 0x31, 0x19, 0x41, 0x1f, 0x45, + 0xce, 0xb5, 0x14, 0x6b, 0x14, 0xd6, 0xef, 0xb8, 0x52, 0x13, 0x2a, 0x18, 0x99, 0x52, 0xef, 0xd8, + 0x1c, 0x33, 0xff, 0xb8, 0x64, 0xdc, 0xe5, 0xe4, 0x2d, 0x00, 0x17, 0x6a, 0x63, 0xdf, 0xf0, 0x0c, + 0x8d, 0xdf, 0x1d, 0xb5, 0xc7, 0xfd, 0xe9, 0x53, 0xda, 0x58, 0xd9, 0x2d, 0xe7, 0xf4, 0x6a, 0xdf, + 0x3d, 0x13, 0x56, 0x6f, 0xe3, 0xc6, 0xf1, 0xe0, 0x25, 0x9c, 0xdc, 0x2a, 0x93, 0x01, 0xb4, 0x57, + 0xb8, 0x75, 0x73, 0xea, 0xc5, 0x45, 0x48, 0xce, 0xe0, 0x38, 0x67, 0xd9, 0x06, 0x2b, 0x73, 0x65, + 0xf2, 0xa2, 0x75, 0xe1, 0x85, 0x37, 0x30, 0xa8, 0xd5, 0x8c, 0x92, 0xc2, 0x20, 0x19, 0x42, 0x6f, + 0x5d, 0x61, 0xc6, 0xf7, 0x46, 0xed, 0x71, 0x2f, 0xae, 0x81, 0xa2, 0x2a, 0xd8, 0x1a, 0x8d, 0x62, + 0xc9, 0x8e, 0xaf, 0x06, 0xc8, 0x03, 0xe8, 0x96, 0xb7, 0xb1, 0x9a, 0x57, 0x95, 0x85, 0x3f, 0x3d, + 0x18, 0xcc, 0x44, 0xfe, 0x81, 0x69, 0xb6, 0x36, 0xff, 0xe2, 0x46, 0xc3, 0xef, 0x1e, 0x9c, 0x36, + 0x1c, 0x54, 0xb3, 0x7a, 0x05, 0x5d, 0xe5, 0x10, 0x37, 0xa8, 0xfe, 0xf4, 0x49, 0x73, 0x8f, 0x77, + 0xda, 0x69, 0x99, 0x96, 0x5b, 0xac, 0x0e, 0x06, 0xcf, 0xa1, 0xdf, 0x80, 0xff, 0x66, 0x7b, 0xd3, + 0x1f, 0x1e, 0x9c, 0xd6, 0xd6, 0x3f, 0xa2, 0xce, 0x79, 0x82, 0xe4, 0x3d, 0x0c, 0x2e, 0xab, 0xff, + 0x69, 0xb7, 0x5b, 0xf2, 0xf0, 0xc0, 0xfd, 0x0a, 0x86, 0xf7, 0x17, 0xcb, 0x6f, 0x0e, 0x8f, 0xc8, + 0x35, 0xfc, 0x7f, 0x89, 0x76, 0xef, 0x86, 0x0c, 0xff, 0x60, 0xb2, 0x64, 0x7b, 0x74, 0x70, 0x04, + 0xe1, 0xd1, 0xeb, 0xf3, 0xcf, 0x93, 0x43, 0x2f, 0xc5, 0xbd, 0x2f, 0xda, 0xbc, 0xeb, 0x1e, 0x86, + 0xf3, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x6a, 0xc2, 0xcc, 0xf4, 0xf1, 0x04, 0x00, 0x00, } diff --git a/reposerver/repository/repository.proto b/reposerver/repository/repository.proto index 5ef92859c3f38..2652520ba6e8e 100644 --- a/reposerver/repository/repository.proto +++ b/reposerver/repository/repository.proto @@ -8,13 +8,14 @@ import "google/api/annotations.proto"; import "k8s.io/api/core/v1/generated.proto"; import "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1/generated.proto"; - // ManifestRequest is a query for manifest generation. message ManifestRequest { github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository repo = 1; string revision = 2; string path = 3; string environment = 4; + string appLabel = 5; + map inputFiles = 6; } message ManifestResponse { diff --git a/server/application/application.go b/server/application/application.go index 06928da6ecb00..e3a905bedaab6 100644 --- a/server/application/application.go +++ b/server/application/application.go @@ -1,8 +1,11 @@ package application import ( + "encoding/json" "fmt" + "strings" + "github.com/argoproj/argo-cd/common" appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1" appclientset "github.com/argoproj/argo-cd/pkg/client/clientset/versioned" "github.com/argoproj/argo-cd/reposerver" @@ -13,9 +16,11 @@ import ( argoutil "github.com/argoproj/argo-cd/util/argo" "github.com/argoproj/argo-cd/util/diff" "github.com/argoproj/argo-cd/util/kube" + "github.com/pborman/uuid" log "github.com/sirupsen/logrus" "golang.org/x/net/context" apiv1 "k8s.io/api/core/v1" + apierr "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/client-go/kubernetes" @@ -71,10 +76,25 @@ func (s *Server) Update(ctx context.Context, a *appv1.Application) (*appv1.Appli return s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Update(a) } -// Delete updates a application -func (s *Server) Delete(ctx context.Context, q *ApplicationQuery) (*ApplicationResponse, error) { +// Delete removes an application and all associated resources +func (s *Server) Delete(ctx context.Context, q *DeleteApplicationRequest) (*ApplicationResponse, error) { err := s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Delete(q.Name, &metav1.DeleteOptions{}) - return &ApplicationResponse{}, err + if err != nil && !apierr.IsNotFound(err) { + return nil, err + } + if q.Server != "" && q.Namespace != "" { + clst, err := s.clusterService.Get(ctx, &cluster.ClusterQuery{Server: q.Server}) + if err != nil { + return nil, err + } + config := clst.RESTConfig() + err = kube.DeleteResourceWithLabel(config, q.Namespace, fmt.Sprintf("%s=%s", common.LabelApplicationName, q.Name)) + if err != nil { + return nil, err + } + } + + return &ApplicationResponse{}, nil } // ListPods returns pods in a application @@ -112,6 +132,27 @@ func (s *Server) Watch(q *ApplicationQuery, ws ApplicationService_WatchServer) e return nil } +func (s *Server) DeployEphemeral(ctx context.Context, req *DeployEphemeralRequest) (*DeployEphemeralResponse, error) { + appName := "app-" + strings.ToLower(uuid.NewRandom().String()) + if req.InputFiles == nil { + req.InputFiles = make(map[string]string) + } + envFileData, err := json.Marshal(map[string]string{"id": appName}) + if err != nil { + return nil, err + } + req.InputFiles["env.libsonnet"] = string(envFileData) + deployResult, err := s.deploy(ctx, *req.Source, req.Destination, appName, req.InputFiles, req.DryRun) + if err != nil { + return nil, err + } + + return &DeployEphemeralResponse{ + AppName: appName, + DeployResult: deployResult, + }, nil +} + // Sync syncs an application to its target state func (s *Server) Sync(ctx context.Context, syncReq *ApplicationSyncRequest) (*ApplicationSyncResult, error) { log.Infof("Syncing application %s", syncReq.Name) @@ -119,27 +160,17 @@ func (s *Server) Sync(ctx context.Context, syncReq *ApplicationSyncRequest) (*Ap if err != nil { return nil, err } - - repo, err := s.repoService.Get(ctx, &apirepository.RepoQuery{Repo: app.Spec.Source.RepoURL}) - if err != nil { - // If we couldn't retrieve from the repo service, assume public repositories - repo = &appv1.Repository{ - Repo: app.Spec.Source.RepoURL, - Username: "", - Password: "", - } + revision := syncReq.Revision + if revision == "" { + app.Spec.Source.TargetRevision = revision } + repo := s.getRepo(ctx, app.Spec.Source.RepoURL) conn, repoClient, err := s.repoClientset.NewRepositoryClient() if err != nil { return nil, err } defer util.Close(conn) - revision := syncReq.Revision - if revision == "" { - revision = app.Spec.Source.TargetRevision - } - // set fields in v1alpha/types.go log.Infof("Retrieving deployment params for application %s", syncReq.Name) deploymentInfo, err := repoClient.GetEnvParams(ctx, &repository.EnvParamsRequest{ @@ -148,26 +179,60 @@ func (s *Server) Sync(ctx context.Context, syncReq *ApplicationSyncRequest) (*Ap Path: app.Spec.Source.Path, Revision: revision, }) + if err != nil { return nil, err } log.Infof("Received deployment params: %s", deploymentInfo.Params) - app.Status.RecentDeployment.Params = deploymentInfo.Params + res, err := s.deploy(ctx, app.Spec.Source, app.Spec.Destination, app.Name, nil, syncReq.DryRun) + if err == nil { + // Persist app deployment info + app.Status.RecentDeployment.Params = deploymentInfo.Params + _, err = s.Update(ctx, app) + if err != nil { + return nil, err + } + } + return res, err +} + +func (s *Server) getRepo(ctx context.Context, repoURL string) *appv1.Repository { + repo, err := s.repoService.Get(ctx, &apirepository.RepoQuery{Repo: repoURL}) + if err != nil { + // If we couldn't retrieve from the repo service, assume public repositories + repo = &appv1.Repository{Repo: repoURL} + } + return repo +} + +func (s *Server) deploy( + ctx context.Context, + source appv1.ApplicationSource, + destination *appv1.ApplicationDestination, + appLabel string, + inputFiles map[string]string, + dryRun bool) (*ApplicationSyncResult, error) { + + repo := s.getRepo(ctx, source.RepoURL) + conn, repoClient, err := s.repoClientset.NewRepositoryClient() if err != nil { return nil, err } + defer util.Close(conn) manifestInfo, err := repoClient.GenerateManifest(ctx, &repository.ManifestRequest{ Repo: repo, - Environment: app.Spec.Source.Environment, - Path: app.Spec.Source.Path, - Revision: revision, + Environment: source.Environment, + Path: source.Path, + Revision: source.TargetRevision, + InputFiles: inputFiles, + AppLabel: appLabel, }) if err != nil { return nil, err } - server, namespace := argoutil.ResolveServerNamespace(app, manifestInfo) + server, namespace := argoutil.ResolveServerNamespace(destination, manifestInfo) clst, err := s.clusterService.Get(ctx, &cluster.ClusterQuery{Server: server}) if err != nil { @@ -203,7 +268,7 @@ func (s *Server) Sync(ctx context.Context, syncReq *ApplicationSyncRequest) (*Ap needsCreate := bool(liveObjs[i] == nil) if !diffRes.Modified { resDetails.Message = fmt.Sprintf("already synced") - } else if syncReq.DryRun { + } else if dryRun { if needsCreate { resDetails.Message = fmt.Sprintf("will create") } else { @@ -222,13 +287,6 @@ func (s *Server) Sync(ctx context.Context, syncReq *ApplicationSyncRequest) (*Ap } syncRes.Resources = append(syncRes.Resources, &resDetails) } - - // Persist app deployment info - _, err = s.Update(ctx, app) - if err != nil { - return nil, err - } - syncRes.Message = "successfully synced" return &syncRes, nil } diff --git a/server/application/application.pb.go b/server/application/application.pb.go index 3e5a7280c072d..b79f2de4c746f 100644 --- a/server/application/application.pb.go +++ b/server/application/application.pb.go @@ -14,9 +14,12 @@ It is generated from these files: It has these top-level messages: ApplicationQuery ApplicationResponse + DeleteApplicationRequest ApplicationSyncRequest ApplicationSyncResult ResourceDetails + DeployEphemeralRequest + DeployEphemeralResponse */ package application @@ -69,6 +72,38 @@ func (m *ApplicationResponse) String() string { return proto.CompactT func (*ApplicationResponse) ProtoMessage() {} func (*ApplicationResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +type DeleteApplicationRequest struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Namespace string `protobuf:"bytes,2,opt,name=namespace" json:"namespace,omitempty"` + Server string `protobuf:"bytes,3,opt,name=server" json:"server,omitempty"` +} + +func (m *DeleteApplicationRequest) Reset() { *m = DeleteApplicationRequest{} } +func (m *DeleteApplicationRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteApplicationRequest) ProtoMessage() {} +func (*DeleteApplicationRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *DeleteApplicationRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *DeleteApplicationRequest) GetNamespace() string { + if m != nil { + return m.Namespace + } + return "" +} + +func (m *DeleteApplicationRequest) GetServer() string { + if m != nil { + return m.Server + } + return "" +} + // ApplicationSyncRequest is a request to apply the config state to live state type ApplicationSyncRequest struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` @@ -79,7 +114,7 @@ type ApplicationSyncRequest struct { func (m *ApplicationSyncRequest) Reset() { *m = ApplicationSyncRequest{} } func (m *ApplicationSyncRequest) String() string { return proto.CompactTextString(m) } func (*ApplicationSyncRequest) ProtoMessage() {} -func (*ApplicationSyncRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (*ApplicationSyncRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } func (m *ApplicationSyncRequest) GetName() string { if m != nil { @@ -111,7 +146,7 @@ type ApplicationSyncResult struct { func (m *ApplicationSyncResult) Reset() { *m = ApplicationSyncResult{} } func (m *ApplicationSyncResult) String() string { return proto.CompactTextString(m) } func (*ApplicationSyncResult) ProtoMessage() {} -func (*ApplicationSyncResult) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } +func (*ApplicationSyncResult) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } func (m *ApplicationSyncResult) GetMessage() string { if m != nil { @@ -137,7 +172,7 @@ type ResourceDetails struct { func (m *ResourceDetails) Reset() { *m = ResourceDetails{} } func (m *ResourceDetails) String() string { return proto.CompactTextString(m) } func (*ResourceDetails) ProtoMessage() {} -func (*ResourceDetails) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } +func (*ResourceDetails) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } func (m *ResourceDetails) GetName() string { if m != nil { @@ -167,12 +202,79 @@ func (m *ResourceDetails) GetMessage() string { return "" } +type DeployEphemeralRequest struct { + Source *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.ApplicationSource `protobuf:"bytes,1,opt,name=source" json:"source,omitempty"` + Destination *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.ApplicationDestination `protobuf:"bytes,2,opt,name=destination" json:"destination,omitempty"` + DryRun bool `protobuf:"varint,3,opt,name=dryRun" json:"dryRun,omitempty"` + InputFiles map[string]string `protobuf:"bytes,4,rep,name=inputFiles" json:"inputFiles,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *DeployEphemeralRequest) Reset() { *m = DeployEphemeralRequest{} } +func (m *DeployEphemeralRequest) String() string { return proto.CompactTextString(m) } +func (*DeployEphemeralRequest) ProtoMessage() {} +func (*DeployEphemeralRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +func (m *DeployEphemeralRequest) GetSource() *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.ApplicationSource { + if m != nil { + return m.Source + } + return nil +} + +func (m *DeployEphemeralRequest) GetDestination() *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.ApplicationDestination { + if m != nil { + return m.Destination + } + return nil +} + +func (m *DeployEphemeralRequest) GetDryRun() bool { + if m != nil { + return m.DryRun + } + return false +} + +func (m *DeployEphemeralRequest) GetInputFiles() map[string]string { + if m != nil { + return m.InputFiles + } + return nil +} + +type DeployEphemeralResponse struct { + AppName string `protobuf:"bytes,1,opt,name=appName" json:"appName,omitempty"` + DeployResult *ApplicationSyncResult `protobuf:"bytes,2,opt,name=deployResult" json:"deployResult,omitempty"` +} + +func (m *DeployEphemeralResponse) Reset() { *m = DeployEphemeralResponse{} } +func (m *DeployEphemeralResponse) String() string { return proto.CompactTextString(m) } +func (*DeployEphemeralResponse) ProtoMessage() {} +func (*DeployEphemeralResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } + +func (m *DeployEphemeralResponse) GetAppName() string { + if m != nil { + return m.AppName + } + return "" +} + +func (m *DeployEphemeralResponse) GetDeployResult() *ApplicationSyncResult { + if m != nil { + return m.DeployResult + } + return nil +} + func init() { proto.RegisterType((*ApplicationQuery)(nil), "application.ApplicationQuery") proto.RegisterType((*ApplicationResponse)(nil), "application.ApplicationResponse") + proto.RegisterType((*DeleteApplicationRequest)(nil), "application.DeleteApplicationRequest") proto.RegisterType((*ApplicationSyncRequest)(nil), "application.ApplicationSyncRequest") proto.RegisterType((*ApplicationSyncResult)(nil), "application.ApplicationSyncResult") proto.RegisterType((*ResourceDetails)(nil), "application.ResourceDetails") + proto.RegisterType((*DeployEphemeralRequest)(nil), "application.DeployEphemeralRequest") + proto.RegisterType((*DeployEphemeralResponse)(nil), "application.DeployEphemeralResponse") } // Reference imports to suppress errors if they are not otherwise used. @@ -192,12 +294,14 @@ type ApplicationServiceClient interface { Watch(ctx context.Context, in *ApplicationQuery, opts ...grpc.CallOption) (ApplicationService_WatchClient, error) // Create creates an application Create(ctx context.Context, in *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Application, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Application, error) + // DeployEphemeral deployes short living application + DeployEphemeral(ctx context.Context, in *DeployEphemeralRequest, opts ...grpc.CallOption) (*DeployEphemeralResponse, error) // Get returns an application by name Get(ctx context.Context, in *ApplicationQuery, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Application, error) // Update updates an application Update(ctx context.Context, in *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Application, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Application, error) // Delete deletes an application - Delete(ctx context.Context, in *ApplicationQuery, opts ...grpc.CallOption) (*ApplicationResponse, error) + Delete(ctx context.Context, in *DeleteApplicationRequest, opts ...grpc.CallOption) (*ApplicationResponse, error) // ListPods returns pods in an application ListPods(ctx context.Context, in *ApplicationQuery, opts ...grpc.CallOption) (*k8s_io_api_core_v1.PodList, error) // Sync syncs an application to its target state @@ -262,6 +366,15 @@ func (c *applicationServiceClient) Create(ctx context.Context, in *github_com_ar return out, nil } +func (c *applicationServiceClient) DeployEphemeral(ctx context.Context, in *DeployEphemeralRequest, opts ...grpc.CallOption) (*DeployEphemeralResponse, error) { + out := new(DeployEphemeralResponse) + err := grpc.Invoke(ctx, "/application.ApplicationService/DeployEphemeral", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *applicationServiceClient) Get(ctx context.Context, in *ApplicationQuery, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Application, error) { out := new(github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Application) err := grpc.Invoke(ctx, "/application.ApplicationService/Get", in, out, c.cc, opts...) @@ -280,7 +393,7 @@ func (c *applicationServiceClient) Update(ctx context.Context, in *github_com_ar return out, nil } -func (c *applicationServiceClient) Delete(ctx context.Context, in *ApplicationQuery, opts ...grpc.CallOption) (*ApplicationResponse, error) { +func (c *applicationServiceClient) Delete(ctx context.Context, in *DeleteApplicationRequest, opts ...grpc.CallOption) (*ApplicationResponse, error) { out := new(ApplicationResponse) err := grpc.Invoke(ctx, "/application.ApplicationService/Delete", in, out, c.cc, opts...) if err != nil { @@ -316,12 +429,14 @@ type ApplicationServiceServer interface { Watch(*ApplicationQuery, ApplicationService_WatchServer) error // Create creates an application Create(context.Context, *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Application) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Application, error) + // DeployEphemeral deployes short living application + DeployEphemeral(context.Context, *DeployEphemeralRequest) (*DeployEphemeralResponse, error) // Get returns an application by name Get(context.Context, *ApplicationQuery) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Application, error) // Update updates an application Update(context.Context, *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Application) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Application, error) // Delete deletes an application - Delete(context.Context, *ApplicationQuery) (*ApplicationResponse, error) + Delete(context.Context, *DeleteApplicationRequest) (*ApplicationResponse, error) // ListPods returns pods in an application ListPods(context.Context, *ApplicationQuery) (*k8s_io_api_core_v1.PodList, error) // Sync syncs an application to its target state @@ -389,6 +504,24 @@ func _ApplicationService_Create_Handler(srv interface{}, ctx context.Context, de return interceptor(ctx, in, info, handler) } +func _ApplicationService_DeployEphemeral_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeployEphemeralRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ApplicationServiceServer).DeployEphemeral(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/application.ApplicationService/DeployEphemeral", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ApplicationServiceServer).DeployEphemeral(ctx, req.(*DeployEphemeralRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _ApplicationService_Get_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ApplicationQuery) if err := dec(in); err != nil { @@ -426,7 +559,7 @@ func _ApplicationService_Update_Handler(srv interface{}, ctx context.Context, de } func _ApplicationService_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ApplicationQuery) + in := new(DeleteApplicationRequest) if err := dec(in); err != nil { return nil, err } @@ -438,7 +571,7 @@ func _ApplicationService_Delete_Handler(srv interface{}, ctx context.Context, de FullMethod: "/application.ApplicationService/Delete", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ApplicationServiceServer).Delete(ctx, req.(*ApplicationQuery)) + return srv.(ApplicationServiceServer).Delete(ctx, req.(*DeleteApplicationRequest)) } return interceptor(ctx, in, info, handler) } @@ -491,6 +624,10 @@ var _ApplicationService_serviceDesc = grpc.ServiceDesc{ MethodName: "Create", Handler: _ApplicationService_Create_Handler, }, + { + MethodName: "DeployEphemeral", + Handler: _ApplicationService_DeployEphemeral_Handler, + }, { MethodName: "Get", Handler: _ApplicationService_Get_Handler, @@ -525,45 +662,59 @@ var _ApplicationService_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("server/application/application.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 639 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x55, 0xc1, 0x6e, 0x13, 0x31, - 0x10, 0xd5, 0xb6, 0x21, 0x34, 0xee, 0x01, 0x64, 0xda, 0x2a, 0x6c, 0x53, 0x11, 0xb9, 0x05, 0x85, - 0x22, 0xbc, 0x4d, 0xb9, 0xa0, 0xde, 0x80, 0x02, 0x02, 0x71, 0x28, 0x8b, 0x10, 0x12, 0x17, 0x70, - 0x77, 0x47, 0x9b, 0x25, 0x89, 0xed, 0xda, 0xde, 0x95, 0x22, 0xe0, 0xc2, 0x0f, 0x20, 0xc4, 0x07, - 0xf0, 0x1d, 0xdc, 0xb9, 0x70, 0xe6, 0x17, 0xf8, 0x10, 0x64, 0x77, 0xd3, 0x6c, 0x9a, 0x34, 0xb9, - 0xe4, 0xc0, 0x6d, 0x3c, 0x33, 0x3b, 0xef, 0xcd, 0xf8, 0xed, 0x18, 0xed, 0x68, 0x50, 0x39, 0xa8, - 0x80, 0x49, 0xd9, 0x4b, 0x23, 0x66, 0x52, 0xc1, 0xcb, 0x36, 0x95, 0x4a, 0x18, 0x81, 0x57, 0x4b, - 0x2e, 0x7f, 0x2d, 0x11, 0x89, 0x70, 0xfe, 0xc0, 0x5a, 0xa7, 0x29, 0x7e, 0x23, 0x11, 0x22, 0xe9, - 0x41, 0xc0, 0x64, 0x1a, 0x30, 0xce, 0x85, 0x71, 0xc9, 0xba, 0x88, 0x92, 0xee, 0x7d, 0x4d, 0x53, - 0xe1, 0xa2, 0x91, 0x50, 0x10, 0xe4, 0xed, 0x20, 0x01, 0x0e, 0x8a, 0x19, 0x88, 0x8b, 0x9c, 0x67, - 0x49, 0x6a, 0x3a, 0xd9, 0x31, 0x8d, 0x44, 0x3f, 0x60, 0xca, 0x41, 0x7c, 0x70, 0xc6, 0xdd, 0x28, - 0x0e, 0x64, 0x37, 0xb1, 0x1f, 0xeb, 0x31, 0xa2, 0x79, 0x9b, 0xf5, 0x64, 0x87, 0x4d, 0x94, 0x22, - 0xb7, 0xd0, 0xd5, 0x07, 0xa3, 0xbc, 0x97, 0x19, 0xa8, 0x01, 0xc6, 0xa8, 0xc2, 0x59, 0x1f, 0xea, - 0x5e, 0xd3, 0x6b, 0xd5, 0x42, 0x67, 0x93, 0x75, 0x74, 0xad, 0x94, 0x17, 0x82, 0x96, 0x82, 0x6b, - 0x20, 0xef, 0xd1, 0x46, 0xc9, 0xfd, 0x6a, 0xc0, 0xa3, 0x10, 0x4e, 0x32, 0xd0, 0x66, 0x5a, 0x11, - 0xec, 0xa3, 0x15, 0x05, 0x79, 0xaa, 0x53, 0xc1, 0xeb, 0x4b, 0xce, 0x7f, 0x76, 0xc6, 0x1b, 0xa8, - 0x1a, 0xab, 0x41, 0x98, 0xf1, 0xfa, 0x72, 0xd3, 0x6b, 0xad, 0x84, 0xc5, 0x89, 0xf4, 0xd1, 0xfa, - 0x04, 0x82, 0xce, 0x7a, 0x06, 0xd7, 0xd1, 0xe5, 0x3e, 0x68, 0xcd, 0x92, 0x21, 0xc6, 0xf0, 0x88, - 0x0f, 0x50, 0x4d, 0x81, 0x16, 0x99, 0x8a, 0x40, 0xd7, 0x97, 0x9a, 0xcb, 0xad, 0xd5, 0xfd, 0x06, - 0x2d, 0x5f, 0x55, 0x58, 0x44, 0x0f, 0xc1, 0xb0, 0xb4, 0xa7, 0xc3, 0x51, 0x3a, 0x39, 0x41, 0x57, - 0xce, 0x45, 0xa7, 0x76, 0x82, 0x51, 0xa5, 0x9b, 0xf2, 0xb8, 0xe8, 0xc2, 0xd9, 0xb8, 0x81, 0x6a, - 0x36, 0xa6, 0x25, 0x8b, 0xc0, 0x35, 0x51, 0x0b, 0x47, 0x8e, 0x32, 0xdd, 0xca, 0x18, 0xdd, 0xfd, - 0x5f, 0x35, 0x84, 0xcb, 0x2d, 0x82, 0xca, 0xd3, 0x08, 0xf0, 0x57, 0x0f, 0x55, 0x5e, 0xa4, 0xda, - 0xe0, 0xad, 0x31, 0xee, 0xe7, 0x6f, 0xcb, 0x7f, 0x4e, 0x47, 0x6a, 0xa0, 0x43, 0x35, 0x38, 0xe3, - 0x5d, 0x14, 0x53, 0xd9, 0x4d, 0xa8, 0x55, 0xc3, 0x58, 0x8d, 0xa1, 0x1a, 0xca, 0xc5, 0x2c, 0x14, - 0x69, 0x7c, 0xf9, 0xf3, 0xf7, 0xfb, 0xd2, 0x06, 0x5e, 0x73, 0xf2, 0xcb, 0xdb, 0x65, 0x0d, 0x69, - 0xfc, 0xc3, 0x43, 0x97, 0xde, 0x30, 0x13, 0x75, 0xe6, 0x51, 0x3a, 0x5a, 0x0c, 0x25, 0x87, 0xf5, - 0x38, 0x07, 0x6e, 0xc8, 0xb6, 0x23, 0xb6, 0x85, 0x37, 0x87, 0xc4, 0xb4, 0x51, 0xc0, 0xfa, 0x63, - 0xfc, 0xf6, 0x3c, 0xfc, 0xd3, 0x43, 0xd5, 0x47, 0x0a, 0x98, 0x01, 0xfc, 0x64, 0x31, 0x1c, 0xfc, - 0x05, 0xd5, 0x21, 0x37, 0x5c, 0x07, 0xd7, 0xc9, 0xd4, 0xd1, 0x1e, 0x78, 0xbb, 0xf8, 0x9b, 0x87, - 0x96, 0x9f, 0xc2, 0xdc, 0xeb, 0x5e, 0x14, 0x9f, 0x89, 0x89, 0x96, 0xf9, 0x04, 0x1f, 0xad, 0x70, - 0x3f, 0xe3, 0xdf, 0x1e, 0xaa, 0xbe, 0x96, 0xf1, 0xff, 0x38, 0xcf, 0xc0, 0xf1, 0xbf, 0xed, 0xef, - 0x4c, 0xe7, 0xdf, 0x07, 0xc3, 0x62, 0x66, 0x18, 0x75, 0x8d, 0xd8, 0xf9, 0x72, 0x54, 0x3d, 0x84, - 0x1e, 0x18, 0x98, 0x37, 0xe1, 0xe6, 0x45, 0xe1, 0xb3, 0xad, 0x57, 0xcc, 0x6e, 0x77, 0xe6, 0xec, - 0x24, 0x5a, 0xb1, 0xff, 0xd4, 0x91, 0x88, 0xf5, 0x3c, 0xc4, 0x4d, 0x7a, 0xba, 0xf4, 0x6d, 0xeb, - 0xd4, 0x2e, 0x7d, 0x9a, 0xb7, 0xe9, 0x91, 0x88, 0xdd, 0x3f, 0xd9, 0x72, 0x60, 0x04, 0x37, 0x67, - 0x80, 0x05, 0xd2, 0xa2, 0x7c, 0x42, 0x15, 0xbb, 0x1f, 0xf1, 0xf6, 0x45, 0x68, 0xa5, 0xfd, 0xec, - 0x93, 0xd9, 0x49, 0x76, 0xc5, 0x92, 0x3b, 0x0e, 0xfa, 0x26, 0x99, 0x09, 0xad, 0x07, 0x3c, 0x3a, - 0xf0, 0x76, 0x1f, 0xee, 0xbd, 0xa5, 0xb3, 0x9e, 0xa5, 0xc9, 0xd7, 0xf3, 0xb8, 0xea, 0x9e, 0xa0, - 0x7b, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0xa6, 0xc6, 0x2d, 0xbc, 0x5a, 0x07, 0x00, 0x00, + // 855 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x56, 0x41, 0x6f, 0xdc, 0x44, + 0x14, 0x96, 0xb3, 0xdb, 0x25, 0x79, 0x8b, 0x94, 0x6a, 0x48, 0xc3, 0xe2, 0xa6, 0x10, 0x4d, 0x52, + 0x94, 0x06, 0x31, 0x6e, 0xd2, 0x4b, 0x15, 0x89, 0x03, 0x90, 0x04, 0x15, 0x55, 0x28, 0x75, 0x85, + 0x90, 0xb8, 0xc0, 0xd4, 0x7e, 0x72, 0xcc, 0x7a, 0x3d, 0xd3, 0x99, 0x59, 0x4b, 0xab, 0xc2, 0x85, + 0x0b, 0x47, 0x84, 0xf8, 0x01, 0xfd, 0x1d, 0xfc, 0x04, 0xce, 0x48, 0xfc, 0x02, 0x7e, 0x08, 0x9a, + 0x59, 0x3b, 0x6b, 0xef, 0x3a, 0x9b, 0x1e, 0xf6, 0xd0, 0x93, 0x67, 0xfc, 0xde, 0xbc, 0xef, 0x7b, + 0xdf, 0x7b, 0x7e, 0x1e, 0xd8, 0xd7, 0xa8, 0x0a, 0x54, 0x01, 0x97, 0x32, 0x4b, 0x23, 0x6e, 0x52, + 0x91, 0xd7, 0xd7, 0x4c, 0x2a, 0x61, 0x04, 0xe9, 0xd7, 0x5e, 0xf9, 0x5b, 0x89, 0x48, 0x84, 0x7b, + 0x1f, 0xd8, 0xd5, 0xd4, 0xc5, 0xdf, 0x49, 0x84, 0x48, 0x32, 0x0c, 0xb8, 0x4c, 0x03, 0x9e, 0xe7, + 0xc2, 0x38, 0x67, 0x5d, 0x5a, 0xe9, 0xf0, 0xb1, 0x66, 0xa9, 0x70, 0xd6, 0x48, 0x28, 0x0c, 0x8a, + 0xa3, 0x20, 0xc1, 0x1c, 0x15, 0x37, 0x18, 0x97, 0x3e, 0x4f, 0x92, 0xd4, 0x5c, 0x8e, 0x5f, 0xb0, + 0x48, 0x8c, 0x02, 0xae, 0x1c, 0xc4, 0x4f, 0x6e, 0xf1, 0x69, 0x14, 0x07, 0x72, 0x98, 0xd8, 0xc3, + 0xba, 0x41, 0xb4, 0x38, 0xe2, 0x99, 0xbc, 0xe4, 0x0b, 0xa1, 0xe8, 0xc7, 0x70, 0xfb, 0xf3, 0x99, + 0xdf, 0xb3, 0x31, 0xaa, 0x09, 0x21, 0xd0, 0xcd, 0xf9, 0x08, 0x07, 0xde, 0xae, 0x77, 0xb0, 0x11, + 0xba, 0x35, 0xbd, 0x03, 0xef, 0xd5, 0xfc, 0x42, 0xd4, 0x52, 0xe4, 0x1a, 0x69, 0x0c, 0x83, 0x53, + 0xcc, 0xd0, 0x60, 0xc3, 0xf8, 0x72, 0x8c, 0xda, 0xb4, 0x85, 0x21, 0x3b, 0xb0, 0x61, 0x9f, 0x5a, + 0xf2, 0x08, 0x07, 0x6b, 0xce, 0x30, 0x7b, 0x41, 0xb6, 0xa1, 0x37, 0x15, 0x79, 0xd0, 0x71, 0xa6, + 0x72, 0x47, 0x7f, 0x84, 0xed, 0x5a, 0xfc, 0xe7, 0x93, 0x3c, 0x5a, 0x86, 0xe1, 0xc3, 0xba, 0xc2, + 0x22, 0xd5, 0xa9, 0xc8, 0x4b, 0x88, 0xab, 0xbd, 0x45, 0x88, 0xd5, 0x24, 0x1c, 0xe7, 0x0e, 0x61, + 0x3d, 0x2c, 0x77, 0x74, 0x04, 0x77, 0x16, 0x10, 0xf4, 0x38, 0x33, 0x64, 0x00, 0xef, 0x8c, 0x50, + 0x6b, 0x9e, 0x54, 0x18, 0xd5, 0x96, 0x9c, 0xc0, 0x86, 0x42, 0x2d, 0xc6, 0x2a, 0x42, 0x3d, 0x58, + 0xdb, 0xed, 0x1c, 0xf4, 0x8f, 0x77, 0x58, 0xbd, 0x21, 0xc2, 0xd2, 0x7a, 0x8a, 0x86, 0xa7, 0x99, + 0x0e, 0x67, 0xee, 0xf4, 0x25, 0x6c, 0xce, 0x59, 0x5b, 0x33, 0x21, 0xd0, 0x1d, 0xa6, 0x79, 0x5c, + 0x66, 0xe1, 0xd6, 0x4d, 0x05, 0x3b, 0xf3, 0x0a, 0xd6, 0xe8, 0x76, 0x1b, 0x74, 0xe9, 0xeb, 0x0e, + 0x6c, 0x9f, 0xa2, 0xcc, 0xc4, 0xe4, 0x4c, 0x5e, 0xe2, 0x08, 0x15, 0xcf, 0x2a, 0x11, 0x63, 0xe8, + 0x4d, 0xb9, 0x38, 0xf0, 0xfe, 0xf1, 0x53, 0x36, 0xeb, 0x2f, 0x56, 0xf5, 0x97, 0x5b, 0xfc, 0x10, + 0xc5, 0x4c, 0x0e, 0x13, 0x66, 0xfb, 0xab, 0x91, 0x6b, 0xd5, 0x5f, 0xac, 0xae, 0xa2, 0x8b, 0x19, + 0x96, 0xb1, 0x89, 0x86, 0x7e, 0x8c, 0xda, 0xa4, 0xb9, 0x33, 0xba, 0x9c, 0xfa, 0xc7, 0xcf, 0x56, + 0x03, 0x75, 0x3a, 0x0b, 0x1c, 0xd6, 0x51, 0xae, 0xab, 0x37, 0x79, 0x0e, 0x90, 0xe6, 0x72, 0x6c, + 0xce, 0xd3, 0x0c, 0xf5, 0xa0, 0xeb, 0xaa, 0xf7, 0xa8, 0x01, 0xd3, 0xae, 0x15, 0x7b, 0x72, 0x75, + 0xea, 0x2c, 0x37, 0x6a, 0x12, 0xd6, 0xc2, 0xf8, 0x9f, 0xc1, 0xe6, 0x9c, 0x99, 0xdc, 0x86, 0xce, + 0x10, 0x27, 0x65, 0x51, 0xed, 0x92, 0x6c, 0xc1, 0xad, 0x82, 0x67, 0xe3, 0xaa, 0xfb, 0xa7, 0x9b, + 0x93, 0xb5, 0xc7, 0x1e, 0x7d, 0x05, 0xef, 0x2f, 0x80, 0x4e, 0x3f, 0x33, 0x5b, 0x56, 0x2e, 0xe5, + 0x37, 0xb3, 0xfe, 0xa8, 0xb6, 0xe4, 0x1c, 0xde, 0x8d, 0xdd, 0xa1, 0x69, 0xbf, 0x96, 0xb2, 0xd2, + 0x46, 0x2a, 0xad, 0x9d, 0x1d, 0x36, 0xce, 0x1d, 0xff, 0x0b, 0x40, 0xea, 0x7e, 0xa8, 0x8a, 0x34, + 0x42, 0xf2, 0xbb, 0x07, 0xdd, 0xa7, 0xa9, 0x36, 0xe4, 0xde, 0x75, 0x11, 0xdd, 0xc8, 0xf0, 0xbf, + 0x5e, 0x4d, 0x1d, 0x2d, 0x14, 0xdd, 0xf9, 0xf5, 0x9f, 0xff, 0xfe, 0x5c, 0xdb, 0x26, 0x5b, 0x6e, + 0x06, 0x16, 0x47, 0xf5, 0x41, 0xa6, 0xc9, 0x6b, 0x0f, 0x6e, 0x7d, 0xc7, 0x4d, 0x74, 0x79, 0x13, + 0xa5, 0x8b, 0xd5, 0x50, 0x72, 0x58, 0x67, 0x05, 0xe6, 0x86, 0xee, 0x39, 0x62, 0xf7, 0xc8, 0xdd, + 0x8a, 0x98, 0x36, 0x0a, 0xf9, 0xa8, 0xc1, 0xef, 0xa1, 0x47, 0xfe, 0xf2, 0xa0, 0xf7, 0xa5, 0x42, + 0x6e, 0x90, 0x9c, 0xaf, 0x86, 0x83, 0xbf, 0xa2, 0x38, 0xf4, 0x23, 0x97, 0xc1, 0x07, 0xb4, 0x55, + 0xda, 0x13, 0xef, 0x90, 0xfc, 0xe6, 0xc1, 0xe6, 0x5c, 0x13, 0x92, 0xbd, 0x37, 0xf8, 0x2e, 0xfc, + 0xfd, 0xe5, 0x4e, 0xe5, 0xef, 0xe2, 0x81, 0xc3, 0xdf, 0xa3, 0x1f, 0xb6, 0xe1, 0x07, 0x58, 0xf9, + 0x5b, 0x26, 0x7f, 0x78, 0xd0, 0xf9, 0x0a, 0x6f, 0x6c, 0xbc, 0x55, 0x29, 0xb3, 0x50, 0xdb, 0x06, + 0xb3, 0x57, 0x76, 0xc2, 0xfe, 0x42, 0xfe, 0xf6, 0xa0, 0xf7, 0xad, 0x8c, 0xdf, 0xc6, 0xca, 0x06, + 0x8e, 0xff, 0x03, 0x7f, 0xbf, 0x9d, 0xff, 0x08, 0x0d, 0x8f, 0xb9, 0xe1, 0xcc, 0x25, 0x62, 0xf5, + 0x2d, 0xa0, 0x37, 0xfd, 0x73, 0x93, 0xfb, 0x73, 0xa5, 0x6b, 0xff, 0x9d, 0xfb, 0xbb, 0xd7, 0x15, + 0xe2, 0xaa, 0xba, 0xa5, 0x86, 0x87, 0x4b, 0x35, 0x94, 0xb0, 0x6e, 0xbf, 0xf2, 0x0b, 0x11, 0xeb, + 0x9b, 0x6a, 0x7b, 0x97, 0x4d, 0xef, 0x42, 0x56, 0x02, 0x66, 0xef, 0x42, 0xac, 0x38, 0x62, 0x17, + 0x22, 0x76, 0x53, 0xe2, 0xc0, 0x81, 0x51, 0xb2, 0xbb, 0x04, 0x2c, 0x90, 0x16, 0xe5, 0x67, 0xe8, + 0xda, 0xb1, 0x37, 0xd7, 0xc7, 0xed, 0x17, 0x0a, 0xff, 0x0d, 0x26, 0x27, 0xfd, 0xc4, 0x41, 0xdf, + 0xa7, 0x4b, 0xa1, 0xf5, 0x24, 0x8f, 0x4e, 0xbc, 0xc3, 0x2f, 0x1e, 0x7e, 0xcf, 0x96, 0xdd, 0xd6, + 0x16, 0x2f, 0x95, 0x2f, 0x7a, 0xee, 0x66, 0xf6, 0xe8, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc2, + 0x38, 0x0e, 0x65, 0x71, 0x0a, 0x00, 0x00, } diff --git a/server/application/application.pb.gw.go b/server/application/application.pb.gw.go index d2135607ce8a5..5815f5b28f06d 100644 --- a/server/application/application.pb.gw.go +++ b/server/application/application.pb.gw.go @@ -84,6 +84,19 @@ func request_ApplicationService_Create_0(ctx context.Context, marshaler runtime. } +func request_ApplicationService_DeployEphemeral_0(ctx context.Context, marshaler runtime.Marshaler, client ApplicationServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq DeployEphemeralRequest + var metadata runtime.ServerMetadata + + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.DeployEphemeral(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + func request_ApplicationService_Get_0(ctx context.Context, marshaler runtime.Marshaler, client ApplicationServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq ApplicationQuery var metadata runtime.ServerMetadata @@ -142,8 +155,12 @@ func request_ApplicationService_Update_0(ctx context.Context, marshaler runtime. } +var ( + filter_ApplicationService_Delete_0 = &utilities.DoubleArray{Encoding: map[string]int{"name": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + func request_ApplicationService_Delete_0(ctx context.Context, marshaler runtime.Marshaler, client ApplicationServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ApplicationQuery + var protoReq DeleteApplicationRequest var metadata runtime.ServerMetadata var ( @@ -164,6 +181,10 @@ func request_ApplicationService_Delete_0(ctx context.Context, marshaler runtime. return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err) } + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_ApplicationService_Delete_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := client.Delete(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err @@ -352,6 +373,35 @@ func RegisterApplicationServiceHandlerClient(ctx context.Context, mux *runtime.S }) + mux.Handle("POST", pattern_ApplicationService_DeployEphemeral_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + if cn, ok := w.(http.CloseNotifier); ok { + go func(done <-chan struct{}, closed <-chan bool) { + select { + case <-done: + case <-closed: + cancel() + } + }(ctx.Done(), cn.CloseNotify()) + } + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_ApplicationService_DeployEphemeral_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_ApplicationService_DeployEphemeral_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_ApplicationService_Get_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -507,6 +557,8 @@ var ( pattern_ApplicationService_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "applications"}, "")) + pattern_ApplicationService_DeployEphemeral_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "applications", "ephemeral"}, "")) + pattern_ApplicationService_Get_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "applications", "name"}, "")) pattern_ApplicationService_Update_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "applications", "metadata.name"}, "")) @@ -525,6 +577,8 @@ var ( forward_ApplicationService_Create_0 = runtime.ForwardResponseMessage + forward_ApplicationService_DeployEphemeral_0 = runtime.ForwardResponseMessage + forward_ApplicationService_Get_0 = runtime.ForwardResponseMessage forward_ApplicationService_Update_0 = runtime.ForwardResponseMessage diff --git a/server/application/application.proto b/server/application/application.proto index 807990b3b333e..5a77b648e2e44 100644 --- a/server/application/application.proto +++ b/server/application/application.proto @@ -19,6 +19,12 @@ message ApplicationQuery { message ApplicationResponse {} +message DeleteApplicationRequest { + string name = 1; + string namespace = 2; + string server = 3; +} + // ApplicationSyncRequest is a request to apply the config state to live state message ApplicationSyncRequest { string name = 1; @@ -39,7 +45,19 @@ message ResourceDetails { string message = 4; } -// ApplicationService +message DeployEphemeralRequest { + github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.ApplicationSource source = 1; + github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.ApplicationDestination destination = 2; + bool dryRun = 3; + map inputFiles = 4; +} + +message DeployEphemeralResponse { + string appName = 1; + ApplicationSyncResult deployResult = 2; +} + +// ApplicationService service ApplicationService { // List returns list of applications @@ -48,7 +66,7 @@ service ApplicationService { } // Watch returns stream of application change events. - rpc Watch(ApplicationQuery) returns (stream github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.ApplicationWatchEvent) { + rpc Watch(ApplicationQuery) returns (stream github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.ApplicationWatchEvent) { option (google.api.http).get = "/api/v1/stream/applications"; } @@ -59,9 +77,17 @@ service ApplicationService { body: "*" }; } - - // Get returns an application by name - rpc Get(ApplicationQuery) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Application) { + + // DeployEphemeral deployes short living application + rpc DeployEphemeral(DeployEphemeralRequest) returns (DeployEphemeralResponse) { + option (google.api.http) = { + post: "/api/v1/applications/ephemeral" + body: "*" + }; + } + + // Get returns an application by name + rpc Get(ApplicationQuery) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Application) { option (google.api.http).get = "/api/v1/applications/{name}"; } @@ -74,7 +100,7 @@ service ApplicationService { } // Delete deletes an application - rpc Delete(ApplicationQuery) returns (ApplicationResponse) { + rpc Delete(DeleteApplicationRequest) returns (ApplicationResponse) { option (google.api.http).delete = "/api/v1/applications/{name}"; } diff --git a/util/argo/argo.go b/util/argo/argo.go index 9076303201056..60b9830cd0b9a 100644 --- a/util/argo/argo.go +++ b/util/argo/argo.go @@ -8,15 +8,15 @@ import ( // ResolveServerNamespace resolves server and namespace to use given an application spec, // and a manifest response. It looks to explicit server/namespace overridden in the app CRD spec // and falls back to the server/namespace defined in the ksonnet environment -func ResolveServerNamespace(app *appv1.Application, manifestInfo *repository.ManifestResponse) (string, string) { +func ResolveServerNamespace(destination *appv1.ApplicationDestination, manifestInfo *repository.ManifestResponse) (string, string) { server := manifestInfo.Server namespace := manifestInfo.Namespace - if app.Spec.Destination != nil { - if app.Spec.Destination.Server != "" { - server = app.Spec.Destination.Server + if destination != nil { + if destination.Server != "" { + server = destination.Server } - if app.Spec.Destination.Namespace != "" { - namespace = app.Spec.Destination.Namespace + if destination.Namespace != "" { + namespace = destination.Namespace } } return server, namespace diff --git a/util/kube/kube.go b/util/kube/kube.go index 1aec6ca849f77..5138acbdbe8f7 100644 --- a/util/kube/kube.go +++ b/util/kube/kube.go @@ -84,6 +84,41 @@ func GetLiveResource(dclient dynamic.Interface, obj *unstructured.Unstructured, return liveObj, nil } +// DeleteResourceWithLabel delete all resources which match to specified label selector +func DeleteResourceWithLabel(config *rest.Config, namespace string, labelSelector string) error { + dynClientPool := dynamic.NewDynamicClientPool(config) + disco, err := discovery.NewDiscoveryClientForConfig(config) + if err != nil { + return err + } + resources, err := disco.ServerResources() + if err != nil { + return err + } + for _, apiResourcesList := range resources { + for _, apiResource := range apiResourcesList.APIResources { + deleteSupported := false + for _, verb := range apiResource.Verbs { + if verb == "deletecollection" { + deleteSupported = true + break + } + } + if deleteSupported { + dclient, err := dynClientPool.ClientForGroupVersionKind(schema.FromAPIVersionAndKind(apiResourcesList.GroupVersion, apiResource.Kind)) + if err != nil { + return err + } + err = dclient.Resource(&apiResource, namespace).DeleteCollection(&metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: labelSelector}) + if err != nil && !apierr.IsNotFound(err) { + return err + } + } + } + } + return nil +} + // GetLiveResources returns the corresponding live resource from a list of resources func GetLiveResources(config *rest.Config, objs []*unstructured.Unstructured, namespace string) ([]*unstructured.Unstructured, error) { liveObjs := make([]*unstructured.Unstructured, len(objs))