Skip to content

Migrating out of spring.profiles.include into spring.profiles.group #24172

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
blacelle opened this issue Nov 17, 2020 · 9 comments
Closed

Migrating out of spring.profiles.include into spring.profiles.group #24172

blacelle opened this issue Nov 17, 2020 · 9 comments

Comments

@blacelle
Copy link
Contributor

blacelle commented Nov 17, 2020

While migrating to SpringBoot 2.4.X, I encountered an issue while migrating from spring.profiles.include. I drop my questions and some supposed answers here. Fact this Upgrading to SpringBoot 2.4 is a pain in our case as we massively rely on spring.profiles.include to chain profile activation, and the documentation/migration notes are unclear for our specific-case.

(Sorry for the quite long ticket. This ticket has been turned from I'm completely lost to Thanks for confirming I'm going the right way, others might be interested)

First, very helpful links:
https://spring.io/blog/2020/08/14/config-file-processing-in-spring-boot-2-4
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Config-Data-Migration-Guide
#22944

Second, would it be relevant to WARN on such deprecated piece of configuration remaining in the project configuration? With a second thought, this looks a bad idea since #21697 restored this property in some usages. But in my case, it took my a while just to understand this property was removed (i.e. my bad, I did not consider going through Release notes, and the Migration Guide).

In our case, we rely massively on spring.profiles.include to triggers profiles chained activation. Typically, we have the following profiles:

  • prod profile, which includes prod-db, prod-queue and prod-common.
  • prod-db includes common-db and prod-common
  • prod-queue includes common-queue and prod-common
  • etc.

The new group features looks great to ensure prod triggers prod-db, prod-queue and prod-common, but I'm not sure what's the proper way to handle the rest of the chain of profiles.

Should I introduce a prod-db groups over common-db and prod-common, and a prod-queue groups over common-queue and prod-common? I guess so.

To confirm what it would look like:

spring.profiles.group.prod-db: common-db,prod-common

However, I also understand I have to pack all these groups into some main application.properties: this is not nice for us as we have many such groups, which are currently described as spring.profiles.include within each profile specific file.

In #22944 (comment), I don't get what is a not in a profile-specific document. Does not in a profile-specific document refers to file being imported through spring.config.import? I guess so.

In addition, given we have multiple applications, each with their own application.yml (and quite a bunch of tests also activating sub-sets of profiles, relying on the chains of profile), I would prefer to push these groups definition into a different specific file. Is spring.config.import the proper way to handle such a case?

I wonder if spring.profiles.include could be restored for simple-single profile-specific documents (e.g. document associated a single and plain profile, not meta-profiles like !dev, nor multi-profile documents).

@blacelle blacelle changed the title Migrating out of spring.profiles.include into Migrating out of spring.profiles.include into spring.profiles.group Nov 17, 2020
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Nov 17, 2020
@philwebb
Copy link
Member

Thanks for opening the issue @blacelle. We suspected that there would be a few users with complex setups like yours that unfortunately will find the upgrade difficult. In the short-term, you can try setting spring.config.use-legacy-processing to true which should restore the old behavior. This will at least allow you to upgrade.

Should I introduce a prod-db groups over common-db and prod-common, and a prod-queue groups over common-queue and prod-common?

Yes, you can define multiple groups, so you should be able to do something like this:

spring:
  profiles:
    group:
      prod: prod-db, prod-queue, prod-common
      prod-db: common-db
      prod-queue: common-queue

I don't get what is a not in a profile-specific document. Does a not in a profile-specific document refers to file being imported through spring.config.import?

This means that you can use spring.profiles.include but you can't combine it with spring.config.activate.on-profile in any way. We now process configs in distinct sweeps and once we've activated the profiles, we don't allow any new config files to be imported.

I would prefer to push these groups definition into a different specific file. Is spring.config.import the proper way to handle such a case?

Yes, you can define your profile groups in a distinct file and import it if you want to. For example you can have an application.yaml file like this:

spring:
  config:
    import: classpath:profile-groups.yaml

Then have a profile-groups.yaml file that defines the groups.

I wonder if spring.profiles.include could be restored for simple-single profile-specific documents (e.g. document associated a single and plain profile, not meta-profiles like !dev, nor multi-profile documents).

This would unfortunately negate most of the benefit that we're trying to achieve with the changes. We're really trying to make our own code much more robust and remove as much complexity as possible.

Please let us know if the profile groups feature works for you. If not, perhaps you can share a sample project that shows your current setup and we can work out if there's something else we can do.

@philwebb philwebb added the status: waiting-for-feedback We need additional information before we can continue label Nov 17, 2020
@blacelle
Copy link
Contributor Author

blacelle commented Nov 17, 2020

We're really trying to make our own code much more robust and remove as much complexity as possible.

I completely catch the point of this evolution.

Still, I'm quite disappointed as I was very happy of leveraging spring.profiles.include as an elegant solution to manage 50+ profiles (various environments, various sub-systems, various 3rd-parties each of them having multiple environments). The bigger pain for me will be to centralised the groups in a single file, making it less readable than current configuration.

About:

I wonder if spring.profiles.include could be restored for simple-single profile-specific documents (e.g. document associated a single and plain profile, not meta-profiles like !dev, nor multi-profile documents).

This would unfortunately negate most of the benefit that we're trying to achieve with the changes.

I supposed it would be quite straightforward if considering only single-simple profiles (just like I may end writing my own spring.profiles.include scanner, to activate the proper profiles before booting). You know better.

Also, what about warning/failing if spring.profiles.include is used in profile-specific documents (and spring.config.use-legacy-processing is not toggled)?

On my side, I'm pretty sure I'll succeed to comply with the new standard. Thanks for the feedback. Feel free to close.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Nov 17, 2020
@philwebb
Copy link
Member

Also, what about warning/failing if spring.profiles.include is used in profile-specific documents (and spring.config.use-legacy-processing is not toggled)?

You should get an exception for that already.

Thinking some more about your use-case. You might be able to use an EnvironmentPostProcessor to activate the profiles programmatically. It's a bit hard to say for sure without seeing a sample app that shows your current setup.

@philwebb philwebb added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Nov 17, 2020
@blacelle
Copy link
Contributor Author

blacelle commented Nov 19, 2020

@philwebb In https://docs.spring.io/spring-boot/docs/2.4.0/reference/htmlsingle/#spring.profiles.include, the lack of impact related to discussed change mislead me in the first step of our migration. I suppose some note may be added there.

You should get an exception for that already.

I definitely did not get one. Especially in unit-tests relying on @ActiveProfiles (i.e. I face this issue by having tests behaving weirdly, it appeared chained profiles were not applying -> no exception, but test broken).

The source of the test is:

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles({ "someDevProfile", "someAppProfiles" })
@ContextConfiguration(classes = { TestConfigFromAzureVault.SpringFromAzureVaultTest.class })
public class TestConfigFromAzureVault {

	@BeforeClass
	public static void assumeInternetIsAvailable() {
		// We need internet access to connect DEV KeyVault
		PepperTestHelper.assumeInternetIsAvailable();
	}

	@Autowired
	Environment env;

	@SpringBootApplication
	public static class SpringFromAzureVaultTest {

	}

	@Test
	public void testSomeSecretFromAzureVault() {
		// This property is defined in Azure KeyVault
		String secretKey = env.getRequiredProperty("azk-keepme-unittest");

		Assert.assertEquals("someSecret", secretKey);
	}
}

Hope it helps.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Nov 19, 2020
@philwebb
Copy link
Member

@blacelle Can you share a small project that shows that full test? I think I need to see the contents of the application.yaml as well.

@philwebb philwebb added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Nov 19, 2020
@spring-projects-issues
Copy link
Collaborator

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

@spring-projects-issues spring-projects-issues added the status: feedback-reminder We've sent a reminder that we need additional information before we can continue label Nov 26, 2020
@spring-projects-issues
Copy link
Collaborator

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.

@spring-projects-issues spring-projects-issues removed status: waiting-for-feedback We need additional information before we can continue status: feedback-reminder We've sent a reminder that we need additional information before we can continue status: waiting-for-triage An issue we've not yet triaged labels Dec 3, 2020
@blling
Copy link

blling commented Dec 11, 2020

Yes, you can define multiple groups, so you should be able to do something like this:

spring:
  profiles:
    group:
      prod: prod-db, prod-queue, prod-common
      prod-db: common-db
      prod-queue: common-queue

I tried, if i have the same properties in common-* and pro-*, it will use the value in common-*, but instead of the value in pro-*. Is this expected ?

@philwebb
Copy link
Member

@blling It's hard to tell without a sample. If you properties are all in one file then it might be the document order.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants