diff --git a/java-cfenv-boot/src/main/java/io/pivotal/cfenv/spring/boot/GenAICfEnvProcessor.java b/java-cfenv-boot/src/main/java/io/pivotal/cfenv/spring/boot/GenAICfEnvProcessor.java new file mode 100644 index 00000000..7f967194 --- /dev/null +++ b/java-cfenv-boot/src/main/java/io/pivotal/cfenv/spring/boot/GenAICfEnvProcessor.java @@ -0,0 +1,51 @@ +/* + * Copyright 2024 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 + * + * https://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 io.pivotal.cfenv.spring.boot; + +import java.util.Map; + +import io.pivotal.cfenv.core.CfCredentials; +import io.pivotal.cfenv.core.CfService; + +/** + * Retrieve GenAI on Tanzu Platform properties from {@link CfCredentials} and + * set {@literal spring.ai} + * Boot properties. + * + * @author Stuart Charlton + **/ +public class GenAICfEnvProcessor implements CfEnvProcessor { + + @Override + public boolean accept(CfService service) { + return service.existsByTagIgnoreCase("genai") || + service.existsByLabelStartsWith("genai"); + } + + @Override + public void process(CfCredentials cfCredentials, Map properties) { + properties.put("spring.ai.openai.base-url", cfCredentials.getString("api_base")); + properties.put("spring.ai.openai.api-key", cfCredentials.getString("api_key")); + } + + @Override + public CfEnvProcessorProperties getProperties() { + return CfEnvProcessorProperties.builder() + .propertyPrefixes("spring.ai.openai") + .serviceName("GenAI on Tanzu Platform") + .build(); + } +} diff --git a/java-cfenv-boot/src/main/resources/META-INF/spring.factories b/java-cfenv-boot/src/main/resources/META-INF/spring.factories index 2450bffb..c99ce64e 100644 --- a/java-cfenv-boot/src/main/resources/META-INF/spring.factories +++ b/java-cfenv-boot/src/main/resources/META-INF/spring.factories @@ -13,6 +13,7 @@ io.pivotal.cfenv.spring.boot.CfEnvProcessor=\ io.pivotal.cfenv.spring.boot.AmqpCfEnvProcessor,\ io.pivotal.cfenv.spring.boot.CredHubCfEnvProcessor,\ io.pivotal.cfenv.spring.boot.CassandraCfEnvProcessor,\ + io.pivotal.cfenv.spring.boot.GenAICfEnvProcessor,\ io.pivotal.cfenv.spring.boot.VaultCfEnvProcessor diff --git a/java-cfenv-boot/src/test/java/io/pivotal/cfenv/spring/boot/GenAICfEnvProcessorTests.java b/java-cfenv-boot/src/test/java/io/pivotal/cfenv/spring/boot/GenAICfEnvProcessorTests.java new file mode 100644 index 00000000..1ce740cc --- /dev/null +++ b/java-cfenv-boot/src/test/java/io/pivotal/cfenv/spring/boot/GenAICfEnvProcessorTests.java @@ -0,0 +1,51 @@ +/* + * Copyright 2024 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 + * + * https://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 io.pivotal.cfenv.spring.boot; + +import mockit.Mock; +import mockit.MockUp; +import org.junit.Test; + +import io.pivotal.cfenv.test.AbstractCfEnvTests; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Stuart Charlton + */ +public class GenAICfEnvProcessorTests extends AbstractCfEnvTests { + + private static final String EXPECTED_TOKEN_FROM_JSON_FILE = "sk-KW5kiNOKDd_1dFxsAjpVa"; + private static final String EXPECTED_URI_FROM_JSON_FILE = "https://genai-proxy.tpcf.io"; + private static final String TEST_GENAI_INFO_JSON = "test-genai-info.json"; + + @Test + public void genaiServiceCreation() { + mockConnectorLibrary(false); + mockVcapServices(getServicesPayload(readTestDataFile(TEST_GENAI_INFO_JSON))); + assertThat(getEnvironment().getProperty("spring.ai.openai.base-url")).isEqualTo(EXPECTED_URI_FROM_JSON_FILE); + assertThat(getEnvironment().getProperty("spring.ai.openai.api-key")).isEqualTo(EXPECTED_TOKEN_FROM_JSON_FILE); + } + + private MockUp mockConnectorLibrary(boolean isUsingConnectorLibrary) { + return new MockUp() { + @Mock + public boolean isUsingConnectorLibrary() { + return isUsingConnectorLibrary; + } + }; + } +} diff --git a/java-cfenv-boot/src/test/resources/io/pivotal/cfenv/spring/boot/test-genai-info.json b/java-cfenv-boot/src/test/resources/io/pivotal/cfenv/spring/boot/test-genai-info.json new file mode 100644 index 00000000..e8785d21 --- /dev/null +++ b/java-cfenv-boot/src/test/resources/io/pivotal/cfenv/spring/boot/test-genai-info.json @@ -0,0 +1,17 @@ +{ + "credentials": { + "api_base": "https://genai-proxy.tpcf.io", + "api_key": "sk-KW5kiNOKDd_1dFxsAjpVa" + }, + "instance_name": "genai", + "label": "genai", + "name": "genai", + "plan": "shared", + "provider": null, + "syslog_drain_url": null, + "tags": [ + "genai", + "llm" + ], + "volume_mounts": [] + } \ No newline at end of file