diff --git a/README.md b/README.md index a4958d427..769af0e4f 100644 --- a/README.md +++ b/README.md @@ -185,7 +185,6 @@ For historical analysis documents from development sessions, see [`docs/archive/ * [Spring Auto Reconfiguration](docs/framework-spring_auto_reconfiguration.md) ([Configuration](docs/framework-spring_auto_reconfiguration.md#configuration)) * [Spring Insight](docs/framework-spring_insight.md) * [SkyWalking Agent](docs/framework-sky_walking_agent.md) ([Configuration](docs/framework-sky_walking_agent.md#configuration)) - * [Takipi Agent](docs/framework-takipi_agent.md) ([Configuration](docs/framework-takipi_agent.md#configuration)) * [YourKit Profiler](docs/framework-your_kit_profiler.md) ([Configuration](docs/framework-your_kit_profiler.md#configuration)) * Standard JREs (Included in Manifest) * [OpenJDK](docs/jre-open_jdk_jre.md) ([Configuration](docs/jre-open_jdk_jre.md#configuration)) - Default diff --git a/docs/framework-ordering.md b/docs/framework-ordering.md index 3362316c1..16537a162 100644 --- a/docs/framework-ordering.md +++ b/docs/framework-ordering.md @@ -52,9 +52,8 @@ Line | Framework Name | Priority | Notes 77 | SpringInsight | 43 | Spring monitoring 78 | SkyWalkingAgent | 44 | APM agent 79 | YourKitProfiler | 45 | Profiler -80 | TakipiAgent | 46 | APM agent -81 | JavaSecurity | 47 | Security configuration -82 | JavaOpts | 99 | ⚠️ USER-DEFINED OPTS (ALWAYS LAST) +80 | JavaSecurity | 47 | Security configuration +81 | JavaOpts | 99 | ⚠️ USER-DEFINED OPTS (ALWAYS LAST) ``` ## Go Buildpack Implementation diff --git a/docs/framework-takipi_agent.md b/docs/framework-takipi_agent.md deleted file mode 100644 index c14805f1b..000000000 --- a/docs/framework-takipi_agent.md +++ /dev/null @@ -1,65 +0,0 @@ -# Takipi Agent Framework -The Takipi Agent Framework causes an application to be automatically configured to work with [OverOps Service][]. - - - - - - - - -
Detection CriterionExistence of a single bound Takipi service. The existence of an Takipi service defined by the VCAP_SERVICES payload containing a service name, label or tag with app-dynamics or takipi as a substring. -
Tagstakipi-agent=<version>
-Tags are printed to standard output by the buildpack detect script - -## User-Provided Service -When binding Takipi using a user-provided service, it must have name or tag with `takipi` in it. -The credential payload can contain the following entries. - -| Name | Description -| ---- | ----------- -| `collector_host` | The remote collector hostname or IP -| `collector_port` | the remote collector port (TCP) -| `secret_key` | (DEPRECATED) The agent installation key for running collector alongside agent - -Setting `collector_host` and `collector_port` will connect to a remote collector. More information can be found in [OverOps Remote Collector][] - -(DEPRECATED)Setting `secret_key` will run a local collector alongside the agent. - -## Configuration -For general information on configuring the buildpack, including how to specify configuration values through environment variables, refer to [Configuration and Extension][]. - -The framework can be configured by modifying the [`config/takipi_agent.yml`][] file. The framework uses the [`Repository` utility support][repositories] and so it supports the [version syntax][] defined there. - -| Name | Description -| ---- | ----------- -| `node_name_prefix` | Node name prefix, will be concatenated with `-` and instance index -| `application_name` | Override the CloudFoundry default application name - -### Remarks -In case **Java 9+** is being used, 2 JVM flags will be added to the execution: -| Name | Description -| ---- | ----------- -| `-XX:-UseTypeSpeculation` | Disable type speculation optimization of the JVM which might not work properly in some situations where an agent is present. -| `-Xshare:off` | Disable class sharing as it might affect the agent's bytecode manipulation work. - -These two flags are needs as otherwise the agent or the JVM might not work properly together. - -## Logs - -Currently, you can view the Takipi agent logs using the `cf ssh` command: -``` -cf ssh app_name -cat ~/app/.java-buildpack/takipi_agent/log/agents/*.log -``` - -## Troubleshooting - -If your container is running out of memory and exited with status 137, then you should setup and use a remote collector as explained in the `User-Provided Service` above section. - -[`config/takipi_agent.yml`]: ../config/takipi_agent.yml -[Configuration and Extension]: ../README.md#configuration-and-extension -[repositories]: extending-repositories.md -[version syntax]: extending-repositories.md#version-syntax-and-ordering -[OverOps Remote Collector]: https://doc.overops.com/docs/install-collector -[OverOps Service]: https://www.overops.com diff --git a/src/integration/frameworks_test.go b/src/integration/frameworks_test.go index 7ce096e68..1ae274d9b 100644 --- a/src/integration/frameworks_test.go +++ b/src/integration/frameworks_test.go @@ -908,27 +908,6 @@ func testFrameworks(platform switchblade.Platform, fixtures string) func(*testin }) }) - context("with Takipi service binding", func() { - it("detects and installs Takipi agent", func() { - t.Skip("SKIPPED: Takipi agent requires valid download URL and SHA256 in manifest.yml") - deployment, logs, err := platform.Deploy. - WithServices(map[string]switchblade.Service{ - "takipi": { - "secret_key": "test-secret-key", - "server": "https://takipi.example.com", - }, - }). - WithEnv(map[string]string{ - "BP_JAVA_VERSION": "11", - }). - Execute(name, filepath.Join(fixtures, "containers", "spring_boot_staged")) - Expect(err).NotTo(HaveOccurred(), logs.String) - - Expect(logs.String()).To(ContainSubstring("Takipi")) - Eventually(deployment).Should(matchers.Serve(ContainSubstring(""))) - }) - }) - context("with Introscope service binding", func() { it("detects and installs Introscope agent", func() { t.Skip("SKIPPED: Introscope agent requires authentication and is not in manifest.yml") @@ -978,7 +957,7 @@ func testFrameworks(platform switchblade.Platform, fixtures string) func(*testin deployment, logs, err := platform.Deploy. WithEnv(map[string]string{ "BP_JAVA_VERSION": "11", - "JBP_CONFIG_ASPECTJ_WEAVER_AGENT": "'{enabled: true}'", + "JBP_CONFIG_ASPECTJ_WEAVER_AGENT": "{ enabled: true }", }). Execute(name, filepath.Join(fixtures, "frameworks", "aspectj_weaver_meta_inf")) Expect(err).NotTo(HaveOccurred(), logs.String) diff --git a/src/java/frameworks/framework.go b/src/java/frameworks/framework.go index 436b60342..6e7a67c04 100644 --- a/src/java/frameworks/framework.go +++ b/src/java/frameworks/framework.go @@ -101,7 +101,6 @@ func (r *Registry) RegisterStandardFrameworks() { r.Register(NewJRebelAgentFramework(r.context)) r.Register(NewContrastSecurityAgentFramework(r.context)) r.Register(NewAspectJWeaverAgentFramework(r.context)) - r.Register(NewTakipiAgentFramework(r.context)) r.Register(NewYourKitProfilerFramework(r.context)) r.Register(NewJProfilerProfilerFramework(r.context)) r.Register(NewSealightsAgentFramework(r.context)) diff --git a/src/java/frameworks/takipi_agent.go b/src/java/frameworks/takipi_agent.go deleted file mode 100644 index 582e5d9dc..000000000 --- a/src/java/frameworks/takipi_agent.go +++ /dev/null @@ -1,177 +0,0 @@ -// Cloud Foundry Java Buildpack -// Copyright 2013-2025 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. - -package frameworks - -import ( - "fmt" - "github.com/cloudfoundry/java-buildpack/src/java/common" - "os" - "path/filepath" - - "github.com/cloudfoundry/libbuildpack" -) - -// TakipiAgentFramework represents the OverOps (formerly Takipi) agent framework -type TakipiAgentFramework struct { - context *common.Context -} - -// NewTakipiAgentFramework creates a new TakipiAgentFramework instance -func NewTakipiAgentFramework(ctx *common.Context) *TakipiAgentFramework { - return &TakipiAgentFramework{context: ctx} -} - -// Detect returns the framework name if a Takipi/OverOps service is bound -func (f *TakipiAgentFramework) Detect() (string, error) { - vcapServices, err := GetVCAPServices() - if err != nil { - return "", nil // Service binding is optional - } - - // Check for service binding (requires 'secret_key' and 'collector_host' credentials) - if vcapServices.HasService("takipi") || - vcapServices.HasService("overops") || - vcapServices.HasTag("takipi") || - vcapServices.HasTag("overops") || - vcapServices.HasServiceByNamePattern("takipi") || - vcapServices.HasServiceByNamePattern("overops") { - return "Takipi Agent", nil - } - - return "", nil -} - -// Supply downloads and installs the Takipi agent -func (f *TakipiAgentFramework) Supply() error { - f.context.Log.Debug("Takipi Agent Supply phase") - - // Get version from manifest - dep := libbuildpack.Dependency{Name: "takipi", Version: ""} - version, err := f.context.Manifest.DefaultVersion(dep.Name) - if err != nil { - return fmt.Errorf("failed to get default version for takipi: %w", err) - } - dep.Version = version.Version - - // Install directory - installDir := filepath.Join(f.context.Stager.DepDir(), "takipi") - - f.context.Log.BeginStep("Installing Takipi Agent %s", dep.Version) - - // Download and extract tarball - if err := f.context.Installer.InstallDependency(dep, installDir); err != nil { - return fmt.Errorf("failed to install takipi: %w", err) - } - - // Create log directory for agents - logDir := filepath.Join(installDir, "log", "agents") - if err := os.MkdirAll(logDir, 0755); err != nil { - return fmt.Errorf("failed to create log directory: %w", err) - } - - f.context.Log.Info("Takipi Agent installed successfully") - return nil -} - -// Finalize configures the Takipi agent runtime environment -func (f *TakipiAgentFramework) Finalize() error { - f.context.Log.Debug("Takipi Agent Finalize phase") - - installDir := filepath.Join(f.context.Stager.DepDir(), "takipi") - agentPath := filepath.Join(installDir, "lib", "libTakipiAgent.so") - - // Verify agent exists - if _, err := os.Stat(agentPath); err != nil { - return fmt.Errorf("takipi agent not found at %s: %w", agentPath, err) - } - - // Get buildpack index for multi-buildpack support - depsIdx := f.context.Stager.DepsIdx() - - // Convert staging path to runtime path - relPath, err := filepath.Rel(f.context.Stager.DepDir(), agentPath) - if err != nil { - return fmt.Errorf("failed to compute relative path: %w", err) - } - runtimeAgentPath := filepath.Join(fmt.Sprintf("$DEPS_DIR/%s", depsIdx), relPath) - - // Get service credentials - vcapServices, err := GetVCAPServices() - if err != nil { - return fmt.Errorf("failed to parse VCAP_SERVICES: %w", err) - } - - // Find Takipi service - var service *VCAPService - if vcapServices.HasService("takipi") { - service = vcapServices.GetService("takipi") - } else if vcapServices.HasService("overops") { - service = vcapServices.GetService("overops") - } else { - service = vcapServices.GetServiceByNamePattern("takipi") - if service == nil { - service = vcapServices.GetServiceByNamePattern("overops") - } - } - - // Add agent to JAVA_OPTS - javaOpts := fmt.Sprintf("-agentpath:%s", runtimeAgentPath) - - // Get application name from VCAP_APPLICATION - appName := os.Getenv("VCAP_APPLICATION") - if appName != "" { - // Parse application name from JSON (simple extraction) - // In production, this would parse the JSON properly - javaOpts += fmt.Sprintf(" -Dtakipi.name=%s", "app") // Simplified - } - - // Add Java 9+ options if needed - javaOpts += " -Xshare:off -XX:-UseTypeSpeculation" - - // Write to .opts file using priority 46 - if err := writeJavaOptsFile(f.context, 46, "takipi", javaOpts); err != nil { - return fmt.Errorf("failed to write java_opts file: %w", err) - } - - // Set environment variables via profile.d (LD_LIBRARY_PATH and Takipi-specific vars) - libPath := fmt.Sprintf("$DEPS_DIR/%s/takipi/lib", depsIdx) - runtimeInstallDir := fmt.Sprintf("$DEPS_DIR/%s/takipi", depsIdx) - - profileContent := fmt.Sprintf(`export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:%s" -export TAKIPI_HOME="%s" -export TAKIPI_MACHINE_NAME="node-$CF_INSTANCE_INDEX" -`, libPath, runtimeInstallDir) - - // Add service credentials as environment variables - if service != nil { - if collectorHost, ok := service.Credentials["collector_host"].(string); ok && collectorHost != "" { - profileContent += fmt.Sprintf("export TAKIPI_COLLECTOR_HOST=\"%s\"\n", collectorHost) - } - if collectorPort, ok := service.Credentials["collector_port"].(string); ok && collectorPort != "" { - profileContent += fmt.Sprintf("export TAKIPI_COLLECTOR_PORT=\"%s\"\n", collectorPort) - } - if secretKey, ok := service.Credentials["secret_key"].(string); ok && secretKey != "" { - profileContent += fmt.Sprintf("export TAKIPI_SECRET_KEY=\"%s\"\n", secretKey) - } - } - - if err := f.context.Stager.WriteProfileD("takipi.sh", profileContent); err != nil { - return fmt.Errorf("failed to write profile script: %w", err) - } - - f.context.Log.Info("Takipi Agent configured (priority 46)") - return nil -} diff --git a/src/java/frameworks/takipi_agent_test.go b/src/java/frameworks/takipi_agent_test.go deleted file mode 100644 index aab6e0f36..000000000 --- a/src/java/frameworks/takipi_agent_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package frameworks_test - -import ( - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -var _ = Describe("TakipiAgent", func() { - It("should require secret_key credential", func() { - credentials := map[string]interface{}{ - "secret_key": "test-secret-key-xyz", - } - - key, ok := credentials["secret_key"].(string) - Expect(ok).To(BeTrue()) - Expect(key).NotTo(BeEmpty()) - }) -})