OctopusDeployLabs / terraform-provider-octopusdeploy

Terraform Provider for Octopus Deploy :octopus:
https://registry.terraform.io/providers/OctopusDeployLabs/octopusdeploy
Mozilla Public License 2.0
82 stars 67 forks source link

Project Versioning Strategy - Donor Package references a Package that hasn't been defined #345

Open FinnianDempsey opened 2 years ago

FinnianDempsey commented 2 years ago

Describe the bug When using the Octopus Terraform Provider to define a project resource. When trying to specify the Project Versioning Strategy from a Donor Package an error is returned: Object reference not set to an instance of an object

Example Template (works fine if the versioning_strategy section is removed):

resource "octopusdeploy_project" "project" {

  lifecycle_id        = "Lifecycles-1"
  name                = "Test TF2"
  project_group_id    = "ProjectGroups-1"
  space_id            = "Default"

  versioning_strategy {
      donor_package {
          package_reference = "webapp"
      }
      donor_package_step_id = "Powershell Hello World"
  }
}

resource "octopusdeploy_deployment_process" "deployment_process" {
  project_id = octopusdeploy_project.project.id 

  step {
    name                = "Powershell Hello World"
    target_roles        = ["local-231"]

    run_script_action {
        name        = "Powershell"
        package {
          name       = "webapp"
          package_id = "webapp"

        }
        script_body                        = <<-EOT
          Write-Host 'Hello world, using PowerShell'
         EOT
    }
  }
}

Expected behavior I would expect to be able to define a Project Versioning Strategy on resource creation.

Logs and other supporting information

2022-03-01 11:28:14.3169   8480     88  WARN  An exception occurred in the Nancy pipeline: "Oh noes!"
Nancy.RequestExecutionException: Oh noes!
 ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at Octopus.Server.Web.Controllers.DeploymentSettings.DeploymentSettingsMapper.GetDonorPackage(VersioningStrategyResource versioningStrategy) in ./source/Octopus.Server/Web/Controllers/DeploymentSettings/DeploymentSettingsMapper.cs:line 44
   at Octopus.Server.Web.Controllers.DeploymentSettings.DeploymentSettingsMapper.Map(ProjectResource resource) in ./source/Octopus.Server/Web/Controllers/DeploymentSettings/DeploymentSettingsMapper.cs:line 26
   at Octopus.Core.Features.Projects.ModifyProjectCommandHandler.Handle(ModifyProjectCommand command, CancellationToken cancellationToken) in ./source/Octopus.Server/Web/Api/Actions/Projects/ProjectModifyCommandHandler.cs:line 138
   at Octopus.Core.Infrastructure.Mediator.AutofacMediator.Do[TCommand,TResponse](ICommand`2 command, CancellationToken cancellationToken) in ./source/Octopus.Core/Infrastructure/Mediator/AutofacMediator.cs:line 29
   at Octopus.Core.Infrastructure.Mediator.Decorators.SystemComponentModelValidationDecorator.Do[TCommand,TResponse](ICommand`2 command, CancellationToken cancellationToken) in ./source/Octopus.Core/Infrastructure/Mediator/Decorators/SystemComponentModelValidationDecorator.cs:line 32
   at Octopus.Core.Infrastructure.Mediator.Decorators.FluentValidationsDecorator.Do[TCommand,TResponse](ICommand`2 command, CancellationToken cancellationToken) in ./source/Octopus.Core/Infrastructure/Mediator/Decorators/FluentValidationsDecorator.cs:line 45
   at Octopus.Core.Infrastructure.Mediator.Decorators.MessageBusSiphoningDecorator.Do[TCommand,TResponse](ICommand`2 command, CancellationToken cancellationToken) in ./source/Octopus.Core/Infrastructure/Mediator/Decorators/MessageBusSiphoningDecorator.cs:line 35
   at Nito.AsyncEx.Synchronous.TaskExtensions.WaitAndUnwrapException[TResult](Task`1 task)
   at Octopus.Server.Web.Api.Actions.Projects.ProjectModifyResponder.ExecuteRegistered() in ./source/Octopus.Server/Web/Api/Actions/Projects/ProjectModifyResponder.cs:line 38
   at Octopus.Server.Web.Infrastructure.Api.CustomResponder`1.Respond(TDescriptor options, NancyContext context) in ./source/Octopus.Server/Web/Infrastructure/Api/CustomResponder.cs:line 321
   at Octopus.Server.Web.Infrastructure.OctopusNancyModule.<>c__DisplayClass14_0.<get_Routes>b__1(Object _, CancellationToken _) in ./source/Octopus.Server/Web/Infrastructure/OctopusNancyModule.cs:line 150
   at Nancy.Routing.Route`1.Invoke(DynamicDictionary parameters, CancellationToken cancellationToken)
   at Nancy.Routing.DefaultRouteInvoker.Invoke(Route route, CancellationToken cancellationToken, DynamicDictionary parameters, NancyContext context)
   at Nancy.Routing.DefaultRequestDispatcher.Dispatch(NancyContext context, CancellationToken cancellationToken)
   at Nancy.NancyEngine.InvokeRequestLifeCycle(NancyContext context, CancellationToken cancellationToken, IPipelines pipelines)
   at Octopus.NancyOwin.NancyMiddleware.RequestComplete(NancyContext context, IDictionary`2 environment, CancellationToken cancellationToken) in ./source/Octopus.Server/Owin/NancyMiddleware.cs:line 174
   at Octopus.NancyOwin.NancyMiddleware.<>c__DisplayClass3_0.<<UseNancy>b__1>d.MoveNext() in ./source/Octopus.Server/Owin/NancyMiddleware.cs:line 110
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Owin.WebSocketAcceptAdapter.<>c__DisplayClass6_0.<<AdaptWebSockets>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.HttpOverrides.HttpMethodOverrideMiddleware.Invoke(HttpContext context)
   at Octopus.Server.Web.UnitOfWorkMiddleware.InvokeAsync(HttpContext httpContext, IUnitOfWork unitOfWork) in ./source/Octopus.Server/Web/UnitOfWorkMiddleware.cs:line 47
   at Octopus.Server.Web.UnitOfWorkMiddleware.InvokeAsync(HttpContext httpContext, IUnitOfWork unitOfWork) in ./source/Octopus.Server/Web/UnitOfWorkMiddleware.cs:line 47
   at Octopus.Server.Web.Middleware.OctopusClientOldVersionWarningMiddleware.InvokeAsync(HttpContext context, IAutomationContext automationContext) in ./source/Octopus.Server/Web/Middleware/OctopusClientOldVersionWarningMiddleware.cs:line 53
   at Octopus.Server.Web.Middleware.DynamicContentHeadersMiddleware.InvokeAsync(HttpContext context) in ./source/Octopus.Server/Web/Middleware/DynamicContentHeadersMiddleware.cs:line 49
   at Octopus.Server.Web.Middleware.MaintenanceModeMiddleware.InvokeAsync(HttpContext context) in ./source/Octopus.Server/Web/Middleware/MaintenanceModeMiddleware.cs:line 61
   at Octopus.Server.Web.Middleware.OctopusAuthenticationMiddleware.InvokeAsync(HttpContext context, CorrelationId correlationId) in ./source/Octopus.Server/Web/Middleware/OctopusAuthenticationMiddleware.cs:line 67
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Octopus.Server.Web.Middleware.LegacyRequestLoggerMiddleware.InvokeAsync(HttpContext context) in ./source/Octopus.Server/Web/Middleware/LegacyRequestLoggerMiddleware.cs:line 42
   at Octopus.Server.Web.Middleware.TelemetryMiddleware.InvokeAsync(HttpContext context) in ./source/Octopus.Server/Web/Middleware/TelemetryMiddleware.cs:line 76
   at Octopus.Server.Web.Middleware.ErrorHandlingMiddleware.InvokeAsync(HttpContext context) in ./source/Octopus.Server/Web/Middleware/ErrorHandlingMiddleware.cs:line 96
   --- End of inner exception stack trace ---
   at Nancy.NancyEngine.InvokeOnErrorHook(NancyContext context, ErrorPipeline pipeline, Exception ex)
2022-03-01 11:28:14.3169   8480     88 ERROR  Unhandled error on request: "Object reference not set to an instance of an object."
System.NullReferenceException: Object reference not set to an instance of an object.
   at Octopus.Server.Web.Controllers.DeploymentSettings.DeploymentSettingsMapper.GetDonorPackage(VersioningStrategyResource versioningStrategy) in ./source/Octopus.Server/Web/Controllers/DeploymentSettings/DeploymentSettingsMapper.cs:line 44
   at Octopus.Server.Web.Controllers.DeploymentSettings.DeploymentSettingsMapper.Map(ProjectResource resource) in ./source/Octopus.Server/Web/Controllers/DeploymentSettings/DeploymentSettingsMapper.cs:line 26
   at Octopus.Core.Features.Projects.ModifyProjectCommandHandler.Handle(ModifyProjectCommand command, CancellationToken cancellationToken) in ./source/Octopus.Server/Web/Api/Actions/Projects/ProjectModifyCommandHandler.cs:line 138
   at Octopus.Core.Infrastructure.Mediator.AutofacMediator.Do[TCommand,TResponse](ICommand`2 command, CancellationToken cancellationToken) in ./source/Octopus.Core/Infrastructure/Mediator/AutofacMediator.cs:line 29
   at Octopus.Core.Infrastructure.Mediator.Decorators.SystemComponentModelValidationDecorator.Do[TCommand,TResponse](ICommand`2 command, CancellationToken cancellationToken) in ./source/Octopus.Core/Infrastructure/Mediator/Decorators/SystemComponentModelValidationDecorator.cs:line 32
   at Octopus.Core.Infrastructure.Mediator.Decorators.FluentValidationsDecorator.Do[TCommand,TResponse](ICommand`2 command, CancellationToken cancellationToken) in ./source/Octopus.Core/Infrastructure/Mediator/Decorators/FluentValidationsDecorator.cs:line 45
   at Octopus.Core.Infrastructure.Mediator.Decorators.MessageBusSiphoningDecorator.Do[TCommand,TResponse](ICommand`2 command, CancellationToken cancellationToken) in ./source/Octopus.Core/Infrastructure/Mediator/Decorators/MessageBusSiphoningDecorator.cs:line 35
   at Nito.AsyncEx.Synchronous.TaskExtensions.WaitAndUnwrapException[TResult](Task`1 task)
   at Octopus.Server.Web.Api.Actions.Projects.ProjectModifyResponder.ExecuteRegistered() in ./source/Octopus.Server/Web/Api/Actions/Projects/ProjectModifyResponder.cs:line 38
   at Octopus.Server.Web.Infrastructure.Api.CustomResponder`1.Respond(TDescriptor options, NancyContext context) in ./source/Octopus.Server/Web/Infrastructure/Api/CustomResponder.cs:line 321
   at Octopus.Server.Web.Infrastructure.OctopusNancyModule.<>c__DisplayClass14_0.<get_Routes>b__1(Object _, CancellationToken _) in ./source/Octopus.Server/Web/Infrastructure/OctopusNancyModule.cs:line 150
   at Nancy.Routing.Route`1.Invoke(DynamicDictionary parameters, CancellationToken cancellationToken)
   at Nancy.Routing.DefaultRouteInvoker.Invoke(Route route, CancellationToken cancellationToken, DynamicDictionary parameters, NancyContext context)
   at Nancy.Routing.DefaultRequestDispatcher.Dispatch(NancyContext context, CancellationToken cancellationToken)
   at Nancy.NancyEngine.InvokeRequestLifeCycle(NancyContext context, CancellationToken cancellationToken, IPipelines pipelines)
   at Octopus.NancyOwin.NancyMiddleware.RequestComplete(NancyContext context, IDictionary`2 environment, CancellationToken cancellationToken) in ./source/Octopus.Server/Owin/NancyMiddleware.cs:line 174
   at Octopus.NancyOwin.NancyMiddleware.<>c__DisplayClass3_0.<<UseNancy>b__1>d.MoveNext() in ./source/Octopus.Server/Owin/NancyMiddleware.cs:line 110
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Owin.WebSocketAcceptAdapter.<>c__DisplayClass6_0.<<AdaptWebSockets>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.HttpOverrides.HttpMethodOverrideMiddleware.Invoke(HttpContext context)
   at Octopus.Server.Web.UnitOfWorkMiddleware.InvokeAsync(HttpContext httpContext, IUnitOfWork unitOfWork) in ./source/Octopus.Server/Web/UnitOfWorkMiddleware.cs:line 47
   at Octopus.Server.Web.UnitOfWorkMiddleware.InvokeAsync(HttpContext httpContext, IUnitOfWork unitOfWork) in ./source/Octopus.Server/Web/UnitOfWorkMiddleware.cs:line 47
   at Octopus.Server.Web.Middleware.OctopusClientOldVersionWarningMiddleware.InvokeAsync(HttpContext context, IAutomationContext automationContext) in ./source/Octopus.Server/Web/Middleware/OctopusClientOldVersionWarningMiddleware.cs:line 53
   at Octopus.Server.Web.Middleware.DynamicContentHeadersMiddleware.InvokeAsync(HttpContext context) in ./source/Octopus.Server/Web/Middleware/DynamicContentHeadersMiddleware.cs:line 49
   at Octopus.Server.Web.Middleware.MaintenanceModeMiddleware.InvokeAsync(HttpContext context) in ./source/Octopus.Server/Web/Middleware/MaintenanceModeMiddleware.cs:line 61
   at Octopus.Server.Web.Middleware.OctopusAuthenticationMiddleware.InvokeAsync(HttpContext context, CorrelationId correlationId) in ./source/Octopus.Server/Web/Middleware/OctopusAuthenticationMiddleware.cs:line 67
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Octopus.Server.Web.Middleware.LegacyRequestLoggerMiddleware.InvokeAsync(HttpContext context) in ./source/Octopus.Server/Web/Middleware/LegacyRequestLoggerMiddleware.cs:line 42
   at Octopus.Server.Web.Middleware.TelemetryMiddleware.InvokeAsync(HttpContext context) in ./source/Octopus.Server/Web/Middleware/TelemetryMiddleware.cs:line 76
   at Octopus.Server.Web.Middleware.ErrorHandlingMiddleware.InvokeAsync(HttpContext context) in ./source/Octopus.Server/Web/Middleware/ErrorHandlingMiddleware.cs:line 96

Screenshots

Screen Shot 2022-03-01 at 11 46 19

Environment and versions:

Additional context Internal Link - Slack Internal Link - Zendesk

jbristowe commented 2 years ago

Proposed Fix:

We need to create a root-level resource to associate a versioning strategy with a project and its deployment process. This can be called something like versioning_strategy_association. This technique is used by other provider vendors such as Amazon and Google. Also, we will need to mark the versioning_strategy as deprecated and provide a new property for the template value, which will be available in the project resource. This property will marked as ConflictsWith for the template property found in versioning_strategy.