diff --git a/Gopkg.lock b/Gopkg.lock index c4cc3e2e..80a273ba 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -2,12 +2,12 @@ [[projects]] - digest = "1:a24d4f0bfca235899423e806a033447bb840d48970ecd8e1bc409537d0289c23" + digest = "1:26ee1e365ea8f312ee11e170fc6675bac0dd3d4adf2406e753d0a43527e1afb8" name = "cloud.google.com/go" packages = ["compute/metadata"] pruneopts = "UT" - revision = "d1af076dc3f6a314e9dd6610fe83b0f7afaff6d6" - version = "v0.45.1" + revision = "264def2dd949cdb8a803bb9f50fa29a67b798a6a" + version = "v0.46.3" [[projects]] digest = "1:7e11a0a4c2d7792a108629e27c83ff4397b950dede4ccce23f99639bfa84846b" @@ -39,12 +39,12 @@ version = "v1.1.0" [[projects]] - digest = "1:8f73e8efaf5aeee6decc946c0ee8b1169a40f3bc5b70731fea56139ef8cb9345" + digest = "1:d37f34e1e231ee4b8657d1b6153e2696b1d7341850f648f5d78151d3bc1f677b" name = "github.com/Masterminds/semver" packages = ["."] pruneopts = "UT" - revision = "0337c9b20b861d2c2e7b25450779f5d91caca32e" - version = "v3.0.0" + revision = "fe7c21038085e01e67044ec1efe3afb1eaa59f75" + version = "v3.0.1" [[projects]] digest = "1:ab506cfc00b11d6d406789c15abb0b341e8db076640e3f5255615a7e327398c1" @@ -469,12 +469,12 @@ version = "v1.0.0" [[projects]] - digest = "1:c1b1102241e7f645bc8e0c22ae352e8f0dc6484b6cb4d132fa9f24174e0119e2" + digest = "1:cc33ef8c2b75f80e588a96f9a70324c0487a02323bd5b2c5d639dda973edc844" name = "github.com/spf13/pflag" packages = ["."] pruneopts = "UT" - revision = "298182f68c66c05229eb03ac171abe6e309ee79a" - version = "v1.0.3" + revision = "e8f29969b682c41a730f8f08b76033b120498464" + version = "v1.0.4" [[projects]] digest = "1:e4ed0afd67bf7be353921665cdac50834c867ff1bba153efc0745b755a7f5905" @@ -577,7 +577,7 @@ "proxy", ] pruneopts = "UT" - revision = "24e19bdeb0f2d062d8e2640d50a7aaf2a7f80e7a" + revision = "c8589233b77dde5edd2205ba8a4fb5c9c2472556" [[projects]] branch = "master" @@ -595,7 +595,7 @@ [[projects]] branch = "master" - digest = "1:55aac9cb3f24f72ab39c28a92666273a4c5df9ab6c30db06a8a5507d47cf667e" + digest = "1:cef0763cedef8416ca6f6f13fa1aadd064736a730f056a7aac30b3b03a82990a" name = "golang.org/x/sys" packages = [ "cpu", @@ -603,7 +603,7 @@ "windows", ] pruneopts = "UT" - revision = "bc967efca4b87fb45e946a3ea4cb891883404fd0" + revision = "b4ddaad3f8a36719f2b8bc6486c14cc468ca2bb5" [[projects]] digest = "1:66a2f252a58b4fbbad0e4e180e1d85a83c222b6bce09c3dcdef3dc87c72eda7c" @@ -924,6 +924,7 @@ analyzer-name = "dep" analyzer-version = 1 input-imports = [ + "github.com/Azure/go-autorest/autorest", "github.com/cloudevents/sdk-go/pkg/cloudevents", "github.com/cloudevents/sdk-go/pkg/cloudevents/types", "github.com/go-openapi/errors", diff --git a/pkg/events/keptnEvents.go b/pkg/events/keptnEvents.go index 276fca9d..318f9e1b 100644 --- a/pkg/events/keptnEvents.go +++ b/pkg/events/keptnEvents.go @@ -2,18 +2,24 @@ package events import "github.com/keptn/go-utils/pkg/models" -// ServiceCreateEventType is a CloudEvent type for creating new services +// ServiceCreateEventType is a CloudEvent type for creating a new service const ServiceCreateEventType = "sh.keptn.event.service.create" -// InternalServiceCreateEventType is a CloudEvent type for creating new services +// InternalServiceCreateEventType is a CloudEvent type for creating a new service const InternalServiceCreateEventType = "sh.keptn.internal.event.service.create" -// ProjectCreateEventType is a CloudEvent type for creating new projects +// ProjectCreateEventType is a CloudEvent type for creating a new project const ProjectCreateEventType = "sh.keptn.event.project.create" -// InternalProjectCreateEventType is a CloudEvent type for creating new projects +// ProjectDeleteEventType is a CloudEvent type for deleting a project +const ProjectDeleteEventType = "sh.keptn.event.project.delete" + +// InternalProjectCreateEventType is a CloudEvent type for creating a new project const InternalProjectCreateEventType = "sh.keptn.internal.event.project.create" +// InternalProjectDeleteEventType is a CloudEvent type for deleting a project +const InternalProjectDeleteEventType = "sh.keptn.internal.event.project.delete" + // ConfigurationChangeEventType is a CloudEvent type for changing the configuration const ConfigurationChangeEventType = "sh.keptn.event.configuration.change" @@ -23,12 +29,27 @@ const ProblemOpenEventType = "sh.keptn.event.problem.open" // ConfigureMonitoringEventType is a CloudEvent for configuring monitoring const ConfigureMonitoringEventType = "sh.keptn.event.monitoring.configure" +// TestsFinishedEventType is a CloudEvent for indicating that tests have finished +const TestsFinishedEventType = "sh.keptn.event.tests.finished" + // ProjectCreateEventData represents the data for creating a new project type ProjectCreateEventData struct { // Project is the name of the project Project string `json:"project"` // Shipyard is a base64 encoded string of the shipyard file Shipyard string `json:"shipyard"` + // GitUser is the name of a git user of an upstream repository + GitUser string `json:"gitUser,omitempty"` + // GitToken is the authentication token for the git user + GitToken string `json:"gitToken,omitempty"` + // GitRemoteURL is the remote url of a repository + GitRemoteURL string `json:"gitRemoteURL,omitempty"` +} + +// ProjectDeleteEventData represents the data for deleting a new project +type ProjectDeleteEventData struct { + // Project is the name of the project + Project string `json:"project"` } // ServiceCreateEventData represents the data for creating a new service @@ -43,7 +64,7 @@ type ServiceCreateEventData struct { DeploymentStrategies map[string]DeploymentStrategy `json:"deploymentStrategies"` } -// ConfigurationChangeEventData represents the data for +// ConfigurationChangeEventData represents the data for changing the service configuration type ConfigurationChangeEventData struct { // Project is the name of the project Project string `json:"project"` @@ -59,6 +80,18 @@ type ConfigurationChangeEventData struct { DeploymentChanges []PropertyChange `json:"deploymentChanges,omitempty"` } +// TestsFinishedEventData represents the data for a test finished event +type TestsFinishedEventData struct { + // Project is the name of the project + Project string `json:"project"` + // Service is the name of the new service + Service string `json:"service"` + // Stage is the name of the stage + Stage string `json:"stage"` + // TestStrategy is the testing strategy + TestStrategy string `json:"teststrategy"` +} + // PropertyChange describes the property to be changed type PropertyChange struct { PropertyPath string `json:"propertyPath"` diff --git a/pkg/models/service_indicators.go b/pkg/models/service_indicators.go index 700a6cbe..97b5f5a5 100644 --- a/pkg/models/service_indicators.go +++ b/pkg/models/service_indicators.go @@ -10,4 +10,10 @@ type ServiceIndicator struct { Metric string `json:"metric" yaml:"metric"` Source string `json:"source" yaml:"source"` Query string `json:"query" yaml:"query"` + QueryObject []*ServiceIndicatorQueryObject `json:"queryObject" yaml:"queryObject"` +} + +type ServiceIndicatorQueryObject struct { + Key string `json:"key" yaml:"key"` + Value string `json:"value" yaml:"value"` } diff --git a/pkg/utils/configServiceUtils.go b/pkg/utils/configServiceUtils.go index afb0d5f8..404da7bf 100644 --- a/pkg/utils/configServiceUtils.go +++ b/pkg/utils/configServiceUtils.go @@ -49,6 +49,42 @@ func post(uri string, data []byte, c ConfigService) (*models.Error, error) { return &respErr, nil } +func delete(uri string, c ConfigService) (*models.Error, error) { + + http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} + req, err := http.NewRequest("DELETE", uri, nil) + req.Header.Set("Content-Type", "application/json") + addAuthHeader(req, c) + + resp, err := c.getHTTPClient().Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode >= 200 && resp.StatusCode < 300 { + return nil, nil + } + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + var respErr models.Error + err = json.Unmarshal(body, &respErr) + if err != nil { + return nil, err + } + + return &respErr, nil +} + +func buildErrorResponse(errorStr string) *models.Error { + err := models.Error{Message: &errorStr} + return &err +} + func addAuthHeader(req *http.Request, c ConfigService) { if c.getAuthHeader() != "" && c.getAuthToken() != "" { req.Header.Set(c.getAuthHeader(), c.getAuthToken()) diff --git a/pkg/utils/helmUtils.go b/pkg/utils/helmUtils.go index f8cdd4b1..f5320c11 100644 --- a/pkg/utils/helmUtils.go +++ b/pkg/utils/helmUtils.go @@ -60,6 +60,11 @@ func LoadChart(data []byte) (*chart.Chart, error) { return chartutil.LoadArchive(bytes.NewReader(data)) } +// LoadChartFromPath loads a directory or Helm chart into a Chart +func LoadChartFromPath(path string) (*chart.Chart, error) { + return chartutil.Load(path) +} + // PackageChart packages the chart and returns it func PackageChart(ch *chart.Chart) ([]byte, error) { helmPackage, err := ioutil.TempDir("", "") diff --git a/pkg/utils/kubeUtils.go b/pkg/utils/kubeUtils.go index 02cd38b1..0a64ce8f 100644 --- a/pkg/utils/kubeUtils.go +++ b/pkg/utils/kubeUtils.go @@ -11,9 +11,11 @@ import ( "k8s.io/client-go/util/retry" appsv1 "k8s.io/api/apps/v1" + typesv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // Initialize all known client auth plugins. + _ "github.com/Azure/go-autorest/autorest" _ "k8s.io/client-go/plugin/pkg/client/auth" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" @@ -53,6 +55,31 @@ func RestartPodsWithSelector(useInClusterConfig bool, namespace string, selector return nil } +func WaitForPodsWithSelector(useInClusterConfig bool, namespace string, selector string, + retries int, waitingTime time.Duration) error { + + clientset, err := GetKubeAPI(useInClusterConfig) + if err != nil { + return err + } + + for i := 0; i < retries; i++ { + pods, err := clientset.Pods(namespace).List(metav1.ListOptions{LabelSelector: selector}) + if err != nil { + return err + } + for _, pod := range pods.Items { + for _, cond := range pod.Status.Conditions { + if cond.Type != typesv1.PodReady { + time.Sleep(waitingTime) + break + } + } + } + } + return nil +} + func ScaleDeployment(useInClusterConfig bool, deployment string, namespace string, replicas int32) error { clientset, err := GetClientset(useInClusterConfig) if err != nil { diff --git a/pkg/utils/projectUtils.go b/pkg/utils/projectUtils.go index e74e9c7e..bef56f2d 100644 --- a/pkg/utils/projectUtils.go +++ b/pkg/utils/projectUtils.go @@ -1,7 +1,9 @@ package utils import ( + "crypto/tls" "encoding/json" + "io/ioutil" "net/http" "strings" @@ -64,10 +66,61 @@ func (p *ProjectHandler) getHTTPClient() *http.Client { // CreateProject creates a new project func (p *ProjectHandler) CreateProject(project models.Project) (*models.Error, error) { - bodyStr, err := json.Marshal(project) if err != nil { return nil, err } return post(p.Scheme+"://"+p.getBaseURL()+"/v1/project", bodyStr, p) } + +// DeleteProject deletes a project +func (p *ProjectHandler) DeleteProject(project models.Project) (*models.Error, error) { + return delete(p.Scheme+"://"+p.getBaseURL()+"/v1/project/"+project.ProjectName, p) +} + +// GetProject returns a project +func (p *ProjectHandler) GetProject(project models.Project) (*models.Project, *models.Error) { + return get(p.Scheme+"://"+p.getBaseURL()+"/v1/project/"+project.ProjectName, p) +} + +func get(uri string, c ConfigService) (*models.Project, *models.Error) { + + http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} + req, err := http.NewRequest("GET", uri, nil) + req.Header.Set("Content-Type", "application/json") + addAuthHeader(req, c) + + resp, err := c.getHTTPClient().Do(req) + if err != nil { + return nil, buildErrorResponse(err.Error()) + } + defer resp.Body.Close() + + if resp.StatusCode >= 200 && resp.StatusCode < 300 { + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, buildErrorResponse(err.Error()) + } + + var respProject models.Project + err = json.Unmarshal(body, &respProject) + if err != nil { + return nil, buildErrorResponse(err.Error()) + } + + return &respProject, nil + } + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, buildErrorResponse(err.Error()) + } + + var respErr models.Error + err = json.Unmarshal(body, &respErr) + if err != nil { + return nil, buildErrorResponse(err.Error()) + } + + return nil, &respErr +} diff --git a/releasenotes/releasenotes_V0.2.1.md b/releasenotes/releasenotes_V0.2.1.md new file mode 100644 index 00000000..dd6fb42a --- /dev/null +++ b/releasenotes/releasenotes_V0.2.1.md @@ -0,0 +1,8 @@ +# Release Notes 0.2.1 + +## New Features +- Add functions for deleting a project [#887](https://github.com/keptn/keptn/issues/887) + +## Fixed Issues + +## Known Limitations diff --git a/version b/version index 0ea3a944..0c62199f 100644 --- a/version +++ b/version @@ -1 +1 @@ -0.2.0 +0.2.1