Skip to content
Closed
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
1 change: 1 addition & 0 deletions config/components.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ frameworks:
- "JavaBuildpack::Framework::PlayFrameworkAutoReconfiguration"
- "JavaBuildpack::Framework::PlayFrameworkJPAPlugin"
- "JavaBuildpack::Framework::PostgresqlJDBC"
- "JavaBuildpack::Framework::RuxitAgent"
- "JavaBuildpack::Framework::SpringAutoReconfiguration"
- "JavaBuildpack::Framework::SpringInsight"
- "JavaBuildpack::Framework::YourKitProfiler"
Expand Down
19 changes: 19 additions & 0 deletions config/ruxit_agent.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Cloud Foundry Java Buildpack
# Copyright (c) 2016 the original author or authors.
#
# 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.

# Configuration for the Ruxit framework
---
version: 1.+
repository_root: http://download.ruxit.com/agent/paas/cloudfoundry/java
47 changes: 47 additions & 0 deletions docs/framework-ruxit_agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Ruxit Agent Framework
The Ruxit Agent Framework causes an application to be automatically configured to work with a bound [Ruxit Service][] instance (Free trials available).

<table>
<tr>
<td><strong>Detection Criterion</strong></td><td>Existence of a single bound Ruxit service.
<ul>
<li>Existence of a Ruxit service is defined as the <a href="http://docs.cloudfoundry.org/devguide/deploy-apps/environment-variable.html#VCAP-SERVICES"><code>VCAP_SERVICES</code></a> payload containing a service who's name, label or tag has <code>ruxit</code> as a substring.</li>
</ul>
</td>
</tr>
<tr>
<td><strong>Tags</strong></td>
<td><tt>ruxit-agent=&lt;version&gt;</tt></td>
</tr>
</table>
Tags are printed to standard output by the buildpack detect script

## User-Provided Service (Optional)
Users may optionally provide their own Ruxit service. A user-provided Ruxit service must have a name or tag with `ruxit` in it so that the Ruxit Agent Framework will automatically configure the application to work with the service.

The credential payload of the service may contain the following entries:

| Name | Description
| ---- | -----------
| `tenant` | Your Ruxit tenant ID is the unique identifier of your Ruxit environment. You can find it easily by looking at the URL in your browser when you are logged into your Ruxit environment. The subdomain {tenant} in https://{tenant}.live.ruxit.com represents your tenant ID.
| `tenanttoken` | The token for your Ruxit environment. You can find it in the deploy Ruxit section within your environment.
| `server` | (Optional) The Ruxit server connection URL to connect to. Use `host:port` format for a specific port number. Uses `https://{tenant}.live.ruxit.com:443/communication` by default.

## Configuration
For general information on configuring the buildpack, including how to specify configuration values through environment variables, refer to [Configuration and Extension][].

Any environment variables with a `RUXIT_` prefix will be relayed to the droplet to allow full configuration of the agent.

The framework can be configured by modifying the [`config/ruxit_agent.yml`][] file in the buildpack fork. The framework uses the [`Repository` utility support][repositories] and so it supports the [version syntax][] defined there.

| Name | Description
| ---- | -----------
| `repository_root` | The URL of the Ruxit repository index ([details][repositories]).
| `version` | The version of Ruxit to use. Candidate versions can be found in [this listing][].

[Configuration and Extension]: ../README.md#configuration-and-extension
[`config/ruxit_agent.yml`]: ../config/ruxit_agent.yml
[Ruxit Service]: https://ruxit.com
[repositories]: extending-repositories.md
[this listing]: http://download.ruxit.com/agent/paas/cloudfoundry/java/index.yml
[version syntax]: extending-repositories.md#version-syntax-and-ordering
153 changes: 153 additions & 0 deletions lib/java_buildpack/framework/ruxit_agent.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# Encoding: utf-8
# Cloud Foundry Java Buildpack
# Copyright 2016 the original author or authors.
#
# 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.

require 'fileutils'
require 'java_buildpack/component/versioned_dependency_component'
require 'java_buildpack/logging/logger_factory'
require 'java_buildpack/framework'
require 'java_buildpack/util/qualify_path'

module JavaBuildpack
module Framework

# Encapsulates the functionality for enabling zero-touch Ruxit support.
class RuxitAgent < JavaBuildpack::Component::VersionedDependencyComponent

# Creates an instance
#
# @param [Hash] context a collection of utilities used the component
def initialize(context)
super(context)
@logger = JavaBuildpack::Logging::LoggerFactory.instance.get_logger RuxitAgent
@logger.debug { "Agent URI to be used: #{@uri.inspect}" }
end

# (see JavaBuildpack::Component::BaseComponent#compile)
def compile
download(@version, @uri) { |file| expand file }
@droplet.copy_resources
end

# (see JavaBuildpack::Component::BaseComponent#release)
def release
credentials = @application.services.find_service(FILTER)['credentials']
environment = @application.environment
java_opts = @droplet.java_opts
droplet_env = @droplet.environment_variables
agent_conf = {}
env = {}

apply_agent_conf(credentials, agent_conf)
apply_user_agent_conf(credentials, agent_conf)
apply_default_environment_variables(env)
apply_user_environment_variables(environment, env)

@logger.debug { "agent_conf: #{agent_conf.inspect}" }
@logger.debug { "ruxit_env: #{env.inspect}" }

env.each do |key, value|
droplet_env.add_environment_variable(key, value)
end
java_opts.add_agentpath_with_props(agent_path, agent_conf)
end

protected

# (see JavaBuildpack::Component::VersionedDependencyComponent#supports?)
def supports?
@application.services.one_service? FILTER, TENANT, TENANT_TOKEN
end

private

FILTER = /ruxit/.freeze
SERVER = 'server'.freeze
TENANT = 'tenant'.freeze
TENANT_TOKEN = 'tenanttoken'.freeze
RUXIT_APPLICATION_ID = 'RUXIT_APPLICATIONID'.freeze
RUXIT_CLUSTER_ID = 'RUXIT_CLUSTER_ID'.freeze
RUXIT_HOST_ID = 'RUXIT_HOST_ID'.freeze

private_constant :FILTER, :SERVER, :TENANT, :TENANT_TOKEN
private_constant :RUXIT_CLUSTER_ID, :RUXIT_APPLICATION_ID, :RUXIT_HOST_ID

def apply_agent_conf(credentials, agent_conf)
agent_conf[SERVER] = server(credentials)
agent_conf[TENANT] = tenant(credentials)
agent_conf[TENANT_TOKEN] = credentials[TENANT_TOKEN]
end

def apply_user_agent_conf(credentials, agent_conf)
credentials.each do |key, value|
agent_conf[key] = value if [SERVER, TENANT, TENANT_TOKEN].include?(key)
end
end

def apply_default_environment_variables(env)
env[RUXIT_APPLICATION_ID] = @application.details['application_name']
env[RUXIT_CLUSTER_ID] = @application.details['application_name']
env[RUXIT_HOST_ID] = "#{@application.details['application_name']}_${CF_INSTANCE_INDEX}"
end

def apply_user_environment_variables(environment, env)
environment.each do |key, value|
env[key] = value if key.start_with?('RUXIT_')
end
end

def server(credentials)
credentials[SERVER] || "https://#{tenant(credentials)}.live.ruxit.com:443/communication"
end

def tenant(credentials)
credentials[TENANT]
end

def agent_dir
@droplet.sandbox + 'agent'
end

def agent_path
agent_dir + lib_name + 'libruxitagentloader.so'
end

def architecture
`uname -m`.strip
end

def expand(file)
with_timing "Expanding Ruxit Agent to #{@droplet.sandbox.relative_path_from(@droplet.root)}" do
Dir.mktmpdir do |root|
root_path = Pathname.new(root)
shell "unzip -qq #{file.path} -d #{root_path} 2>&1"
unpack_agent root_path
end
end
end

def lib_name
architecture == 'x86_64' || architecture == 'i686' ? 'lib64' : 'lib'
end

def unpack_agent(root)
FileUtils.mkdir_p(agent_dir)
FileUtils.mv(root + 'agent/bin', agent_dir)
FileUtils.mv(root + 'agent/conf', agent_dir)
FileUtils.mv(root + 'agent' + lib_name, agent_dir)
end
end
end
end
Binary file added spec/fixtures/stub-ruxit-agent.zip
Binary file not shown.
58 changes: 58 additions & 0 deletions spec/java_buildpack/framework/ruxit_agent_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Encoding: utf-8
# Cloud Foundry Java Buildpack
# Copyright 2016 the original author or authors.
#
# 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.

require 'spec_helper'
require 'component_helper'
require 'java_buildpack/framework/ruxit_agent'
require 'java_buildpack/util/tokenized_version'

describe JavaBuildpack::Framework::RuxitAgent do
include_context 'component_helper'

it 'does not detect without ruxit-n/a service' do
expect(component.detect).to be_nil
end

context do

before do
allow(services).to receive(:one_service?).with(/ruxit/, 'tenant', 'tenanttoken').and_return(true)
end

it 'detects with ruxit-n/a service' do
expect(component.detect).to eq("ruxit-agent=#{version}")
end

it 'downloads Ruxit agent zip',
cache_fixture: 'stub-ruxit-agent.zip' do

component.compile

expect(sandbox + 'agent/lib64/libruxitagentloader.so').to exist
end

it 'updates JAVA_OPTS' do
allow(services).to receive(:find_service).and_return('credentials' => { 'tenant' => 'testtenant',
'tenanttoken' => 'testtoken' })
component.release

expect(java_opts).to include('-agentpath:$PWD/.java-buildpack/ruxit_agent/agent/lib64/libruxitagentloader.so='\
'server=https://testtenant.live.ruxit.com:443/communication,tenant=testtenant,tenanttoken=testtoken')
end

end

end