ActionTemplate usage update

Hi! I’m trying to update action template usage through your c# client.
There is method:

Task<ActionUpdateResultResource[]> UpdateActions(ActionTemplateResource actionTemplate, ActionsUpdateResource update)

What is ActionsUpdateResource? How can i get them in client for certain action template?

Kind regards,
Alexander Yuzhanin

Hi Alexander,

Thanks for contacting us. The ActionUpdateResource is only used when updating values in an ActionTemplate, so there’s no way to get them. Instead the code should create a ActionUpdateResource and then send it to the server to update an existing ActionTemplateResource.

Hope that helps.

Hi, Cameron!
Thank you for the answer. May be my question wasn’t clear enough, i’ll try to ask it in other words:
How can i get all of action template usages and update them using octopus.client (on c#)?

Kind regards,
Alexander Yuzhanin

Hi Alexander,

Ah, I understand now. First of, I’m guessing you’re using our nuget package https://www.nuget.org/packages/Octopus.Client/ If not start by installing that.

Then, here’s some sample code that will go through each ActionTemplate and update it.

var endpoint = new OctopusServerEndpoint("http://octopus");
var repository = new OctopusRepository(endpoint);
repository.Users.SignIn("Admin", "password");

var actionTemplates = repository.ActionTemplates.GetAll();
foreach (var actionTemplate in actionTemplates)
{
    var actionUpdate = new ActionsUpdateResource();
    // Set values to modify to the actionUpdate here    
    var results = repository.ActionTemplates.UpdateActions(actionTemplate, actionUpdate);
}

Hi, Cameron!

Thank you for the answer. Yes, i’m using your client and have some additional questions to your answer.
I’am writing an action-template sync-daemon. First of all i’am updating action template in octopus. And then i want to update all of it’s realisations in actions. (i want to write an analog of button “update all” that presented in octopus interface).
I’ll add some my code to a better explanation:

                        using (var client = await OctopusAsyncClient.Create(OctopusServerEndpoint).ConfigureAwait(false))
                        {
                            var remoteTemplate = await client.Repository.ActionTemplates.FindByName(templateToSync.Name).ConfigureAwait(false);

                            var updateTemplateResource = templateToSync.GetUpdateTemplate(remoteTemplate);
                            await client.Repository.ActionTemplates.Modify(updateTemplateResource).ConfigureAwait(false);
                             //here is some method for "update all action"       
                            await UpdateUsage(templateToSync.Name, taskMultiplier).ConfigureAwait(false);
                            
                        }

According to your answer, i can get all actions inherited from a certain template, but what should i wrote in

?

Kind regards,
Alexander Yuzhanin

Ok. Here’s some C# code that will update all the usages of all the action templates.

var actionTemplates = repository.ActionTemplates.GetAll();
foreach (var actionTemplate in actionTemplates)
{		
	var usages = client.Get<ActionTemplateUsageResource[]>(actionTemplate.Links["Usage"]);
	var usagesToUpdate = usages.Where(u => u.Version != actionTemplate.Version.ToString());
	
	if (!usagesToUpdate.Any()) continue;
	
	var actionsByProcessId = usagesToUpdate.GroupBy(u => u.DeploymentProcessId);
	var actionIdsByProcessId = actionsByProcessId.ToDictionary(g => g.Key, g => g.Select(u => u.ActionId).ToArray());
			
	var actionUpdate = new ActionsUpdateResource();
	actionUpdate.Version = actionTemplate.Version;
	actionUpdate.ActionIdsByProcessId = actionIdsByProcessId;
	actionUpdate.Overrides = actionTemplate.Parameters.ToDictionary(p => p.Name, p => p.DefaultValue);
	repository.ActionTemplates.UpdateActions(actionTemplate, actionUpdate);
}

Thank you for your code, it’s clear enough now. But i have one more question - how “Overrides” works? it will replace overrided values by default ones? And there is one more property in object initialiser - DefaultPropertyValues - should i fill it before update?

Kind regards, Alexander Yuzhanin

Hi again, i tried to use your code. It overrides action parameters by default value from action template :frowning:

Kind regards, Alexander Yuzhanin.

@distantcam please see to the code below

                var actualTemplateState = await client.Repository.ActionTemplates.FindByName(templateName).ConfigureAwait(false);
                if (actualTemplateState == null)
                {
                    Log.Warn($"Can't get actual state for {templateName}");
                    return;
                }

                var actualVersion = actualTemplateState.Version;
                var usages = await client.Get<ActionTemplateUsageResource[]>(actualTemplateState.Links["Usage"]).ConfigureAwait(false);
                var usagesToUpdate = usages.Where(u => u.Version != actualVersion.ToString()).ToList();
                if (!usagesToUpdate.Any())
                {
                    Log.Info($"All usages of {templateName} are in actual state");
                    return;
                }

                foreach (var usageToUpdate in usagesToUpdate)
                {
                    var deploymentProcess = await client.Repository.DeploymentProcesses.Get(usageToUpdate.DeploymentProcessId);
                    var step = deploymentProcess.Steps.FirstOrDefault(x => x.Id == usageToUpdate.StepId);
                    var action = step?.Actions.FirstOrDefault(x => x.Id == usageToUpdate.ActionId);
                    var actionUpdateResource = new ActionsUpdateResource
                    {
                        Version = actualVersion,
                        ActionIdsByProcessId = new Dictionary<string, string[]>
                        {
                            {usageToUpdate.DeploymentProcessId, new[] {usageToUpdate.ActionId}}
                        },
                        Overrides = action?.Properties.Where(x => actualTemplateState.Parameters.Any(y=> y.Name == x.Key)).ToDictionary(p=> p.Key, p=> p.Value),
                        DefaultPropertyValues = actualTemplateState.Parameters.ToDictionary(p => p.Name, p => p.DefaultValue)
                    };
                    var updateResult = await client.Repository.ActionTemplates.UpdateActions(actualTemplateState, actionUpdateResource).ConfigureAwait(false);

Am i right with Overrides and DefaultPropertyValues usage?

Ah ok. The overrides might not be needed, but you may get an error when updating some actions. Try it without the overrides and see how you go.

The reason why I needed to provide overrides was because of this issue https://github.com/OctopusDeploy/Issues/issues/2954 where some of my templates had default values and therefore I had to provide overrides. It might be better to customise this code for each template type.

Thank you, it seems like i can use ActionsUpdateResource without Overrides and DefaultPropertyValues.

Kind regards,
Alexander Yuzhanin

That’s great! Glad to hear you’ve got it working.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.