// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.

= Apache NiFi Quickstart

Below is a brief example using Apache NiFi to ingest data in Apache Kudu.

== Start the Kudu Quickstart Environment

See the Apache Kudu
link:https://kudu.apache.org/docs/quickstart.html[quickstart documentation]
to setup and run the Kudu quickstart environment.

== Run Apache NiFi

Use the following command to run the latest Apache NiFi Docker image:

[source,bash]
----
docker run -d --name kudu-nifi --network="docker_default" -p 8080:8080 apache/nifi:latest
----

You can view the running NiFi instance at link:http://localhost:8080/nifi[localhost:8080/nifi].

NOTE: `--network="docker_default"` is specified to connect the container the
same network as the quickstart cluster.

NOTE: You can remove the `-d` flag to run the container in the foreground.

== Create the Kudu table

Create the `random_user` Kudu table that matches the expected Schema.

In order to do this without any dependencies on your host machine, we will
use the `jshell` REPL in a Docker container to create the table using the
Java API. First setup the Docker container, download the jar, and run the REPL:

[source,bash]
----
docker run -it --rm --network="docker_default" maven:latest bin/bash
# Download the kudu-client-tools jar which has the kudu-client and all the dependencies.
mkdir jars
mvn dependency:copy \
    -Dartifact=org.apache.kudu:kudu-client-tools:1.15.0 \
    -DoutputDirectory=jars
# Run the jshell with the jar on the classpath.
jshell --class-path jars/*
----

NOTE: `--network="docker_default"` is specified to connect the container the
same network as the quickstart cluster.

Then, once in the `jshell` REPL, create the table using the Java API:

[source,java]
----
import org.apache.kudu.client.CreateTableOptions
import org.apache.kudu.client.KuduClient
import org.apache.kudu.client.KuduClient.KuduClientBuilder
import org.apache.kudu.ColumnSchema.ColumnSchemaBuilder
import org.apache.kudu.Schema
import org.apache.kudu.Type

KuduClient client =
  new KuduClientBuilder("kudu-master-1:7051,kudu-master-2:7151,kudu-master-3:7251").build();

if(client.tableExists("random_user")) {
  client.deleteTable("random_user");
}

Schema schema = new Schema(Arrays.asList(
  new ColumnSchemaBuilder("ssn", Type.STRING).key(true).build(),
  new ColumnSchemaBuilder("firstName", Type.STRING).build(),
  new ColumnSchemaBuilder("lastName", Type.STRING).build(),
  new ColumnSchemaBuilder("email", Type.STRING).build())
);
CreateTableOptions tableOptions =
  new CreateTableOptions().setNumReplicas(3).addHashPartitions(Arrays.asList("ssn"), 4);
client.createTable("random_user", schema, tableOptions);
----

Once complete, you can use `CTRL + D` to exit the REPL and `exit` to exit the container.

== Load the Dataflow Template

The `Random_User_Kudu.xml` template downloads randomly generated user data from
http://randomuser.me and then pushes the data into Kudu. The data is pulled in
100 records at a time and then split into individual records. The incoming data
is in JSON Format.

Next, the user's social security number, first name, last name, and e-mail
address are extract from the JSON into FlowFile Attributes and the content is
modified to become a new JSON document consisting of only 4 fields:
`ssn`, `firstName`, `lastName`, and `email`. Finally, this smaller JSON is then pushed to
Kudu as a single row, each field being a separate column in that row.

To load the template follow the NiFi
link:https://nifi.apache.org/docs/nifi-docs/html/user-guide.html#Import_Template["Importing a Template" documentation]
to load `Random_User_Kudu.xml`.

Then follow the NiFi
link:hhttps://nifi.apache.org/docs/nifi-docs/html/user-guide.html#instantiating-a-template["Instantiating a Template" documentation]
to add the `Random User Kudu` template to the canvas.

Once the template is added to the canvas you need to start the JsonTreeReader
controller service. You can do this via the PutKudu processor configuration
or via the Nifi Flow configuration in the Operate panel. See the Nifi
link:https://nifi.apache.org/docs/nifi-docs/html/user-guide.html#Controller_Services_for_Dataflows["Controller Service" documentation]
for more details.

Now you can start individual processors by right-clicking each processor and selecting `Start`.
You can also explore the configuration, queue contents, and more by right-clicking on each element.
Alternatively you can use the Operate panel and start the entire flow at once.
More about starting and stopping NiFi components can be read in the NiFi
link:https://nifi.apache.org/docs/nifi-docs/html/user-guide.html#starting-a-component["Starting a Component" documentation].

== Shutdown NiFi

Once you are done with the NiFi container you can shutdown in a couple of ways.
If you ran NiFi without the `-d` flag, you can use `ctrl + c` to stop the container.

If you ran NiFi with the `-d` flag, you can use the following to
gracefully shutdown the container:

[source,bash]
----
docker stop kudu-nifi
----

To permanently remove the container run the following:

[source,bash]
----
docker rm kudu-nifi
----

== Next steps

The above example showed how to ingest data into Kudu using Apache NiFi.
Next explore the other quickstart guides to learn how to query or process
the data using other tools.

For example, the link:https://github.com/apache/kudu/tree/master/examples/quickstart/spark[Spark quickstart guide]
will walk you through how to setup and query Kudu tables with the `spark-kudu`
integration.

If you have already run through the Spark quickstart the following is a brief
example of the code to allow you to query the `random_user` table:

[source,bash]
----
spark-shell --packages org.apache.kudu:kudu-spark2_2.11:1.15.0
----

[source,scala]
----
:paste
val random_user = spark.read
	.option("kudu.master", "localhost:7051,localhost:7151,localhost:7251")
	.option("kudu.table", "random_user")
	// We need to use leader_only because Kudu on Docker currently doesn't
	// support Snapshot scans due to `--use_hybrid_clock=false`.
	.option("kudu.scanLocality", "leader_only")
	.format("kudu").load
random_user.createOrReplaceTempView("random_user")
spark.sql("SELECT count(*) FROM random_user").show()
spark.sql("SELECT * FROM random_user LIMIT 5").show()
----

== Help

If have questions, issues, or feedback on this quickstart guide, please reach out to the
link:https://kudu.apache.org/community.html[Apache Kudu community].
