Skip to content
This repository has been archived by the owner on Mar 14, 2024. It is now read-only.

[KOGITO-1294] Adding support for binary builds #201

Merged
merged 1 commit into from
Mar 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 52 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ Table of Contents
=================

* [Kogito Operator](#kogito-operator)
* [Table of Contents](#table-of-contents)
* [Kogito Operator requirements](#kogito-operator-requirements)
* [Kogito Operator installation](#kogito-operator-installation)
* [Deploying to OpenShift 4.x](#deploying-to-openshift-4x)
Expand All @@ -18,6 +17,7 @@ Table of Contents
* [Deploying to OpenShift 3.11](#deploying-to-openshift-311)
* [Kogito Runtimes service deployment](#kogito-runtimes-service-deployment)
* [Deploying a new service](#deploying-a-new-service)
* [Binary Builds](#binary-builds)
* [Cleaning up a Kogito service deployment](#cleaning-up-a-kogito-service-deployment)
* [Native X JVM builds](#native-x-jvm-builds)
* [Troubleshooting Kogito Runtimes service deployment](#troubleshooting-kogito-runtimes-service-deployment)
Expand All @@ -42,6 +42,7 @@ Table of Contents
* [For Linux and macOS](#for-linux-and-macos)
* [For Windows](#for-windows)
* [Building the Kogito CLI from source](#building-the-kogito-cli-from-source)
* [Kogito CLI output format and environment variables](#kogito-cli-output-format-and-environment-variables)
* [Deploying a Kogito service from source with the Kogito CLI](#deploying-a-kogito-service-from-source-with-the-kogito-cli)
* [Prometheus integration with the Kogito Operator](#prometheus-integration-with-the-kogito-operator)
* [Prometheus annotations](#prometheus-annotations)
Expand All @@ -55,7 +56,7 @@ Table of Contents
* [Kogito Operator development](#kogito-operator-development)
* [Building the Kogito Operator](#building-the-kogito-operator)
* [Deploying to OpenShift 4.x for development purposes](#deploying-to-openshift-4x-for-development-purposes)
* [Running BDD tests](#running-bdd-tests)
* [Running BDD Tests](#running-bdd-tests)
* [Running BDD tests with current branch](#running-bdd-tests-with-current-branch)
* [Running BDD tests with custom Kogito Build images' version](#running-bdd-tests-with-custom-kogito-build-images-version)
* [Running smoke tests](#running-smoke-tests)
Expand Down Expand Up @@ -139,6 +140,55 @@ Alternatively, you can use the [Kogito CLI](#kogito-cli) to deploy your services
$ kogito deploy-service example-quarkus https://github.com/kiegroup/kogito-examples/ --context-dir=drools-quarkus-example
```

### Binary Builds

Kogito Operator can configure a build for you that will pull and build your application through the source to image (s2i)
feature (available only on OpenShift).

Instead of using the cluster to build your entire application, you can upload your Kogito Service application binaries to the
cluster using **binary builds**. To create a new service without a specific Git URL, run the following command:

```bash
$ kogito deploy-service example-quarkus
```

Access your application directory and run the following:

```bash
$ mvn clean package
```

This command produces a target directory that contains all your binary files:

```bash
$ ls -l target/

total 372
drwxrwxr-x. 4 ricferna ricferna 4096 Mar 10 16:01 classes
-rw-rw-r--. 1 ricferna ricferna 19667 Mar 10 16:01 drools-quarkus-example-8.0.0-SNAPSHOT.jar
-rw-r--r--. 1 ricferna ricferna 311190 Mar 10 16:01 drools-quarkus-example-8.0.0-SNAPSHOT-runner.jar
-rw-rw-r--. 1 ricferna ricferna 14168 Mar 10 16:01 drools-quarkus-example-8.0.0-SNAPSHOT-sources.jar
drwxrwxr-x. 3 ricferna ricferna 4096 Mar 10 16:01 generated-sources
-rw-rw-r--. 1 ricferna ricferna 24 Mar 10 16:01 image_metadata.json
drwxrwxr-x. 2 ricferna ricferna 12288 Mar 10 16:01 lib
drwxrwxr-x. 2 ricferna ricferna 4096 Mar 10 16:01 maven-archiver
drwxrwxr-x. 3 ricferna ricferna 4096 Mar 10 16:01 maven-status
```

You can upload the entire directory to the cluster or you might elect only the relevant files:

1. The `jar` runner and the `lib` directory for Quarkus runtime or just the uber jar if you're using Springboot
2. The `classes/persistence` directory where resides the generated protobuf files.
3. The `image_metadata.json` file, which contains the information about the image that will be built by the s2i feature

Use the `oc` client to upload and start the image build:

```bash
oc start-build example-quarkus-binary --from-dir=target
```
And that's it. In a couple minutes you should have your Kogito Service application up and running using the same binaries
built locally.

### Cleaning up a Kogito service deployment

```bash
Expand Down
55 changes: 34 additions & 21 deletions cmd/kogito/command/deploy/deploy_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package deploy
import (
"fmt"
"github.com/kiegroup/kogito-cloud-operator/cmd/kogito/command/context"
"github.com/kiegroup/kogito-cloud-operator/cmd/kogito/command/message"
"github.com/kiegroup/kogito-cloud-operator/cmd/kogito/command/shared"
"github.com/kiegroup/kogito-cloud-operator/pkg/apis/app/v1alpha1"
"github.com/kiegroup/kogito-cloud-operator/pkg/client/kubernetes"
Expand Down Expand Up @@ -83,12 +84,13 @@ func (i *deployCommand) Command() *cobra.Command {

func (i *deployCommand) RegisterHook() {
i.command = &cobra.Command{
Use: "deploy-service NAME SOURCE",
Use: "deploy-service NAME [SOURCE]",
Short: "Deploys a new Kogito Runtime Service into the given Project",
Aliases: []string{"deploy"},
Long: `deploy-service will create a new Kogito Runtime Service from source in the Project context.
Long: `deploy-service will create a new Kogito Runtime Service in the Project context.
If the source is provided, the build will take place on the cluster, otherwise you must upload the application binaries via "oc start-build [NAME-binary] --from-dir=target".
Project context is the namespace (Kubernetes) or project (OpenShift) where the Service will be deployed.
To know what's your context, use "kogito use-project". To set a new Project in the context use "kogito use-project NAME".
To know what's your context, use "kogito project". To set a new Project in the context use "kogito use-project NAME".

Please note that this command requires the Kogito Operator installed in the cluster.
For more information about the Kogito Operator installation please refer to https://github.com/kiegroup/kogito-cloud-operator#kogito-operator-installation.
Expand All @@ -98,11 +100,13 @@ func (i *deployCommand) RegisterHook() {
PostRun: i.CommonPostRun,
// Args validation
Args: func(cmd *cobra.Command, args []string) error {
if len(args) != 2 {
return fmt.Errorf("requires 2 args, received %v", len(args))
if len(args) > 2 {
return fmt.Errorf("requires 1 arg, received %v", len(args))
}
if _, err := url.ParseRequestURI(args[1]); err != nil {
return fmt.Errorf("source is not a valid URL, received %s", args[1])
if len(args) > 1 {
if _, err := url.ParseRequestURI(args[1]); err != nil {
return fmt.Errorf("source is not a valid URL, received %s", args[1])
}
}
if err := util.ParseStringsForKeyPair(i.flags.buildEnv); err != nil {
return fmt.Errorf("build environment variables are in the wrong format. Valid are key pairs like 'env=value', received %s", i.flags.buildEnv)
Expand Down Expand Up @@ -161,11 +165,14 @@ func (i *deployCommand) InitHook() {
i.command.Flags().BoolVar(&i.flags.enableIstio, "enable-istio", false, "Enable Istio integration by annotating the Kogito service pods with the right value for Istio controller to inject sidecars on it. Defaults to false")
}

func (i *deployCommand) Exec(cmd *cobra.Command, args []string) error {
func (i *deployCommand) Exec(cmd *cobra.Command, args []string) (err error) {
log := context.GetDefaultLogger()
i.flags.name = args[0]
i.flags.source = args[1]
var err error
hasSource := false
if len(args) > 1 {
i.flags.source = args[1]
hasSource = true
}

if len(i.flags.mavenMirrorURL) > 0 {
if _, err := url.ParseRequestURI(i.flags.mavenMirrorURL); err != nil {
Expand Down Expand Up @@ -204,13 +211,8 @@ func (i *deployCommand) Exec(cmd *cobra.Command, args []string) error {
Replicas: &i.flags.Replicas,
Runtime: v1alpha1.RuntimeType(i.flags.runtime),
Build: &v1alpha1.KogitoAppBuildObject{
Incremental: i.flags.incrementalBuild,
Env: shared.FromStringArrayToControllerEnvs(i.flags.buildEnv),
GitSource: &v1alpha1.GitSource{
URI: &i.flags.source,
ContextDir: i.flags.contextDir,
Reference: i.flags.reference,
},
Incremental: i.flags.incrementalBuild,
Env: shared.FromStringArrayToControllerEnvs(i.flags.buildEnv),
ImageS2ITag: i.flags.imageS2I,
ImageRuntimeTag: i.flags.imageRuntime,
ImageVersion: i.flags.imageVersion,
Expand All @@ -237,16 +239,27 @@ func (i *deployCommand) Exec(cmd *cobra.Command, args []string) error {
},
}

if hasSource {
kogitoApp.Spec.Build.GitSource = v1alpha1.GitSource{
URI: i.flags.source,
ContextDir: i.flags.contextDir,
Reference: i.flags.reference,
}
}

log.Debugf("Trying to deploy Kogito Service '%s'", kogitoApp.Name)
// Create the Kogito application
if err := kubernetes.ResourceC(i.Client).Create(kogitoApp); err != nil {
return fmt.Errorf("Error while creating a new KogitoApp in the context: %v ", err)
}

log.Infof("KogitoApp '%s' successfully created on namespace '%s'", kogitoApp.Name, kogitoApp.Namespace)
// TODO: We should provide this info with a -f flag
log.Infof("You can see the deployment status by using 'oc describe %s %s -n %s'", "kogitoapp", i.flags.name, i.flags.Project)
log.Infof("Your Kogito Runtime Service should be deploying. To see its logs, run 'oc logs -f bc/%s-builder -n %s'", i.flags.name, i.flags.Project)
log.Infof(message.KogitoAppSuccessfullyCreated, kogitoApp.Name, kogitoApp.Namespace)
if hasSource {
log.Infof(message.KogitoAppViewDeploymentStatus, i.flags.name, i.flags.Project)
log.Infof(message.KogitoAppViewBuildStatus, i.flags.name, i.flags.Project)
} else {
log.Infof(message.KogitoAppUploadBinariesInstruction, i.flags.name, i.flags.Project)
}

return nil
}
27 changes: 26 additions & 1 deletion cmd/kogito/command/deploy/deploy_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func Test_DeployCmd_OperatorAutoInstal(t *testing.T) {
func Test_DeployCmd_OperatorAutoInstall(t *testing.T) {
ns := t.Name()
cli := fmt.Sprintf("deploy-service example-drools https://github.com/kiegroup/kogito-examples --context-dir drools-quarkus-example --project %s", ns)
test.SetupCliTest(cli,
Expand Down Expand Up @@ -149,3 +149,28 @@ func Test_DeployCmd_WithInvalidMavenMirrorURL(t *testing.T) {
_, _, err := test.ExecuteCli()
assert.Error(t, err)
}

func Test_DeployCmd_WithoutGitURL(t *testing.T) {
ns := t.Name()
cli := fmt.Sprintf("deploy-service example-drools -p %s", ns)
test.SetupCliTest(cli,
context.CommandFactory{BuildCommands: BuildCommands},
&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ns}},
&apiextensionsv1beta1.CustomResourceDefinition{ObjectMeta: metav1.ObjectMeta{Name: v1alpha1.KogitoAppCRDName}})
lines, _, err := test.ExecuteCli()
assert.NoError(t, err)
assert.Contains(t, lines, "example-drools")
assert.Contains(t, lines, "-binary")
assert.NotContains(t, lines, "deploying")
}

func Test_DeployCmd_WrongGitURL(t *testing.T) {
ns := t.Name()
cli := fmt.Sprintf("deploy-service example-drools invalid url -p %s", ns)
test.SetupCliTest(cli,
context.CommandFactory{BuildCommands: BuildCommands},
&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ns}},
&apiextensionsv1beta1.CustomResourceDefinition{ObjectMeta: metav1.ObjectMeta{Name: v1alpha1.KogitoAppCRDName}})
_, _, err := test.ExecuteCli()
assert.Error(t, err)
}
8 changes: 0 additions & 8 deletions cmd/kogito/command/message/infra.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,12 @@ package message

// Messages for Infrastructure components
const (
KogitoInfraErrCreating = "Error while trying to create a new Kogito Infra: %s "

InfinispanErrInstalling = "Error while trying to install Infinispan: %s "
InfinispanSuccessfulInstalled = "Infinispan has been successfully installed in the Project %s."
InfinispanErrRemoving = "Error while trying to remove Infinispan: %s "
InfinispanSuccessfulRemoved = "Infinispan has been successfully removed from the Project %s."

KafkaErrInstalling = "Error while trying to install Kafka: %s "
KafkaSuccessfulInstalled = "Kafka has been successfully installed in the Project %s."
KafkaErrRemoving = "Error while trying to remove Kafka: %s "
KafkaSuccessfulRemoved = "Kafka has been successfully removed from the Project %s."

KeycloakErrInstalling = "Error while trying to install Keycloak: %s "
KeycloakSuccessfulInstalled = "Keycloak has been successfully installed in the Project %s."
KeycloakErrRemoving = "Error while trying to remove Keycloak: %s "
KeycloakSuccessfulRemoved = "Keycloak has been successfully removed from the Project %s."
)
23 changes: 23 additions & 0 deletions cmd/kogito/command/message/kogitoapp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2020 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 message

// Messages for KogitoApp deployment
const (
KogitoAppSuccessfullyCreated = "KogitoApp '%s' successfully created on namespace '%s'"
KogitoAppViewDeploymentStatus = "You can see the deployment status by using 'oc describe kogitoapp %s -n %s'"
KogitoAppViewBuildStatus = "Your Kogito Runtime Service should be deploying. To see its logs, run 'oc logs -f bc/%s-builder -n %s'"
KogitoAppUploadBinariesInstruction = "Your Kogito Runtime Service needs the application binaries to proceed. To upload your binaries please run 'oc start-build %s-binary --from-dir=target -n %s' from your project's root"
)
7 changes: 3 additions & 4 deletions deploy/crds/app.kiegroup.org_kogitoapps_crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ spec:
type: object
type: array
gitSource:
description: GitSource Git coordinates to locate the source code
to build
description: Information about the git repository where the Kogito
App source code resides. If set, the operator will use source
to image strategy build.
properties:
contextDir:
description: Context/subdirectory where the code is located,
Expand Down Expand Up @@ -149,8 +150,6 @@ spec:
type: string
type: object
type: array
required:
- gitSource
type: object
enableIstio:
description: Annotates the pods managed by the operator with the required
Expand Down
10 changes: 10 additions & 0 deletions deploy/examples/jbpm-quarkus-example-binary-builds.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: app.kiegroup.org/v1alpha1
kind: KogitoApp
metadata:
name: example-quarkus-flash
spec:
# you only need to inform the correct image tag if you wish to build from a custom image
build:
imageVersion: 0.8.0-rc3 # will use it as a reference to create the imagestreams that the Operator uses
imageRuntimeTag: quay.io/ricardozanini/kogito-quarkus-jvm-ubi8:0.8.0-rc4 # custom image used by runtime/binary builds
# run this from your terminal on your project's root: oc start-build example-quarkus-flash-binary --from-dir=target
Loading