blob: 902882994a41439cba3808fa5d244b9b4baa7905 [file] [log] [blame]
// Copyright 2019 Red Hat, Inc. and/or its affiliates
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package framework
import (
"fmt"
"time"
"github.com/apache/incubator-kie-kogito-serverless-operator/bddframework/pkg/api"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
ocapps "github.com/openshift/api/apps/v1"
buildv1 "github.com/openshift/api/build/v1"
imagev1 "github.com/openshift/api/image/v1"
routev1 "github.com/openshift/api/route/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
"github.com/apache/incubator-kie-kogito-serverless-operator/bddframework/pkg/config"
"github.com/apache/incubator-kie-kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes"
)
const (
dockerImageKind = "DockerImage"
)
// WaitForBuildConfigCreated waits for a build config to be created
func WaitForBuildConfigCreated(namespace, buildConfigName string, timeoutInMin int) error {
return WaitForOnOpenshift(namespace, fmt.Sprintf("BuildConfig %s created", buildConfigName), timeoutInMin,
func() (bool, error) {
if bc, err := getBuildConfig(namespace, buildConfigName); err != nil {
return false, err
} else if bc == nil {
return false, nil
}
return true, nil
})
}
// WaitForBuildConfigCreatedWithWebhooks waits for a build config to be created with webhooks
func WaitForBuildConfigCreatedWithWebhooks(namespace, buildConfigName string, expectedWebhooks []api.WebHookSecretInterface, timeoutInMin int) error {
return WaitForOnOpenshift(namespace, fmt.Sprintf("BuildConfig %s created with webhooks", buildConfigName), timeoutInMin,
func() (bool, error) {
if bc, err := getBuildConfig(namespace, buildConfigName); err != nil {
return checkWebhooksInBuildConfig(namespace, bc.Spec.Triggers, expectedWebhooks), err
} else if bc == nil {
return false, nil
}
return true, nil
})
}
func checkWebhooksInBuildConfig(namespace string, actual []buildv1.BuildTriggerPolicy, expected []api.WebHookSecretInterface) bool {
for _, expectedWebhook := range expected {
for _, actualTrigger := range actual {
var typedTrigger *buildv1.WebHookTrigger
switch expectedWebhook.GetType() {
case api.GitHubWebHook:
typedTrigger = actualTrigger.GitHubWebHook
case api.GenericWebHook:
typedTrigger = actualTrigger.GenericWebHook
}
if typedTrigger == nil || typedTrigger.SecretReference.Name != expectedWebhook.GetSecret() {
return false
}
}
}
return true
}
func getBuildConfig(namespace, buildConfigName string) (*buildv1.BuildConfig, error) {
bc := &buildv1.BuildConfig{}
if exists, err := kubernetes.ResourceC(kubeClient).FetchWithKey(types.NamespacedName{Name: buildConfigName, Namespace: namespace}, bc); err != nil && !errors.IsNotFound(err) {
return nil, fmt.Errorf("Error while trying to look for BuildConfig %s: %v ", buildConfigName, err)
} else if errors.IsNotFound(err) || !exists {
return nil, nil
}
return bc, nil
}
// WaitForDeploymentConfigRunning waits for a deployment config to be running, with a specific number of pod
func WaitForDeploymentConfigRunning(namespace, dcName string, podNb int, timeoutInMin int) error {
return WaitForOnOpenshift(namespace, fmt.Sprintf("DeploymentConfig %s running", dcName), timeoutInMin,
func() (bool, error) {
if dc, err := GetDeploymentConfig(namespace, dcName); err != nil {
return false, err
} else if dc == nil {
return false, nil
} else {
GetLogger(namespace).Debug("Deployment config has", "available replicas", dc.Status.AvailableReplicas)
return dc.Status.AvailableReplicas == int32(podNb), nil
}
}, CheckPodsByDeploymentConfigInError(namespace, dcName))
}
// GetDeploymentConfig retrieves a deployment config
func GetDeploymentConfig(namespace, dcName string) (*ocapps.DeploymentConfig, error) {
dc := &ocapps.DeploymentConfig{}
if exists, err := kubernetes.ResourceC(kubeClient).FetchWithKey(types.NamespacedName{Name: dcName, Namespace: namespace}, dc); err != nil && !errors.IsNotFound(err) {
return nil, fmt.Errorf("Error while trying to look for DeploymentConfig %s: %v ", dcName, err)
} else if errors.IsNotFound(err) || !exists {
return nil, nil
}
return dc, nil
}
// WaitForRoute waits for a route to be available
func WaitForRoute(namespace, routeName string, timeoutInMin int) error {
return WaitForOnOpenshift(namespace, fmt.Sprintf("Route %s available", routeName), timeoutInMin,
func() (bool, error) {
route, err := GetRoute(namespace, routeName)
if err != nil || route == nil {
return false, err
}
return true, nil
})
}
// GetRoute retrieves a route
func GetRoute(namespace, routeName string) (*routev1.Route, error) {
route := &routev1.Route{}
if exists, err :=
kubernetes.ResourceC(kubeClient).FetchWithKey(types.NamespacedName{Name: routeName, Namespace: namespace}, route); err != nil {
return nil, err
} else if !exists {
return nil, nil
} else {
return route, nil
}
}
func createHTTPRoute(namespace, serviceName string) error {
GetLogger(namespace).Info("Creating HTTP route", "serviceName", serviceName)
route := &routev1.Route{
ObjectMeta: metav1.ObjectMeta{
Name: serviceName,
Namespace: namespace,
},
Spec: routev1.RouteSpec{
To: routev1.RouteTargetReference{
Kind: "Service",
Name: serviceName,
},
},
}
if err := kubernetes.ResourceC(kubeClient).Create(route); err != nil {
return err
}
return nil
}
// GetRouteURI retrieves a route URI
func GetRouteURI(namespace, serviceName string) (string, error) {
if err := WaitForRoute(namespace, serviceName, 2); err != nil {
return "", fmt.Errorf("Route %s does not exist in namespace %s: %v", serviceName, namespace, err)
}
route, err := GetRoute(namespace, serviceName)
if err != nil || route == nil {
return "", err
}
host := route.Spec.Host
protocol := "http"
port := "80"
if route.Spec.TLS != nil {
protocol = "https"
port = "443"
}
uri := protocol + "://" + host + ":" + port
return uri, nil
}
// CreateInsecureImageStream creates insecure ImageStream pointing to the passed image tag
func CreateInsecureImageStream(namespace, imageStreamName, imageTag, imageFullName string) error {
GetLogger(namespace).Info("Creating insecure ImageStream", "name", imageStreamName, "imageTag", imageTag, "imageFullName", imageFullName)
imageStream := &imagev1.ImageStream{
ObjectMeta: metav1.ObjectMeta{
Name: imageStreamName,
Namespace: namespace,
},
Spec: imagev1.ImageStreamSpec{
Tags: []imagev1.TagReference{
{
Name: imageTag,
ImportPolicy: imagev1.TagImportPolicy{
Insecure: true,
},
ReferencePolicy: imagev1.TagReferencePolicy{
Type: imagev1.LocalTagReferencePolicy,
},
From: &corev1.ObjectReference{
Kind: dockerImageKind,
Name: imageFullName,
},
},
},
},
}
if err := kubernetes.ResourceC(kubeClient).Create(imageStream); err != nil {
return err
}
return nil
}
// GetImageStreams returns ImageStreams in the namespace
func GetImageStreams(namespace string) (*imagev1.ImageStreamList, error) {
imageStreams := &imagev1.ImageStreamList{}
if err := GetObjectsInNamespace(namespace, imageStreams); err != nil {
return nil, err
}
return imageStreams, nil
}
// WaitForOnOpenshift waits for a specification condition
func WaitForOnOpenshift(namespace, display string, timeoutInMin int, condition func() (bool, error), errorConditions ...func() (bool, error)) error {
return WaitFor(namespace, display, GetOpenshiftDurationFromTimeInMin(timeoutInMin), condition, errorConditions...)
}
// GetOpenshiftDurationFromTimeInMin will calculate the time depending on the configured cluster load factor
func GetOpenshiftDurationFromTimeInMin(timeoutInMin int) time.Duration {
return time.Duration(timeoutInMin*config.GetLoadFactor()) * time.Minute
}