Cake 构建脚本调用 AWS.ElasticBeanstalk DescribeEnvironments() 抛出 MissingMethodException

Cake build script calling AWS.ElasticBeanstalk DescribeEnvironments() throwing MissingMethodException

这是一个非常具体的错误,过去几天我一直在调查它,但遇到了死胡同。

我的蛋糕构建脚本中的一项任务是尝试检查弹性 beantalk 环境是否准备就绪。我们一直在使用这个插件 (https://github.com/mathieukempe/Cake.AWS.ElasticBeanstalk) 我分叉了 repo 以添加 DescribeEnvironments() 实现。如果我直接在控制台应用程序中 运行 它,插件代码就可以工作。然而,当我 运行 它从蛋糕构建脚本中抛出 System.MissingMethodException: Method not found: 'System.String Amazon.Runtime.Internal.Util.StringUtils.FromDateTimeToISO8601(System.DateTime)' 不幸的是,我认为我是互联网上唯一遇到此问题的人。

下面是我的蛋糕脚本是运行ning:

的任务
Task("CheckEBEnvironment")
.Does((context) => {
    var settings = CreateElasticBeanstalkSettings();
    if (context.ApplicationVersionReady(settings, ebApplication, ebEnvironment, ebVersion)) {
        Information("Environment ready.");
        isReady = true;
    } else {
        Information("Environment not ready...");
    } 
});

下面是插件代码:

[CakeAliasCategory("AWS")]
[CakeNamespaceImport("Amazon")]
[CakeNamespaceImport("Amazon.ElasticBeanstalk")]
public static class ElasticBeanstalkAliases
{
    private static IElasticBeanstalkManager CreateManager(this ICakeContext context)
    {
        return new ElasticBeanstalkManager(context.Environment, context.Log);
    }

    // ...

    [CakeMethodAlias]
    [CakeAliasCategory("ElasticBeanstalk")]
    public static bool ApplicationVersionReady(this ICakeContext context, ElasticBeanstalkSettings settings, string applicationName, string environmentName, string versionLabel)
    {
        var manager = context.CreateManager();
        return manager.ApplicationVersionReady(settings, applicationName, environmentName, versionLabel);
    }
}

实现如下:

public class ElasticBeanstalkManager : IElasticBeanstalkManager
{
    private readonly ICakeEnvironment _Environment;
    private readonly ICakeLog _Log;

    /// <summary>
    /// If the manager should output progrtess events to the cake log
    /// </summary>
    public bool LogProgress { get; set; }

    public ElasticBeanstalkManager(ICakeEnvironment environment, ICakeLog log)
    {
        if (environment == null)
        {
            throw new ArgumentNullException("environment");
        }
        if (log == null)
        {
            throw new ArgumentNullException("log");
        }

        _Environment = environment;
        _Log = log;

        this.LogProgress = true;
    }

    //Request
    private AmazonElasticBeanstalkClient GetClient(ElasticBeanstalkSettings settings)
    {
        if (settings == null)
        {
            throw new ArgumentNullException("settings");
        }

        if (settings.Region == null)
        {
            throw new ArgumentNullException("settings.Region");
        }

        if (settings.Credentials == null)
        {
            if (String.IsNullOrEmpty(settings.AccessKey))
            {
                throw new ArgumentNullException("settings.AccessKey");
            }
            if (String.IsNullOrEmpty(settings.SecretKey))
            {
                throw new ArgumentNullException("settings.SecretKey");
            }

            return new AmazonElasticBeanstalkClient(settings.AccessKey, settings.SecretKey, settings.Region);
        }
        else
        {
            return new AmazonElasticBeanstalkClient(settings.Credentials, settings.Region);
        }
    }

    public bool ApplicationVersionReady(ElasticBeanstalkSettings settings, string applicationName, string environmentName, string versionLabel)
    {
        if (string.IsNullOrEmpty(applicationName))
        {
            throw new ArgumentNullException(nameof(applicationName));
        }

        if (string.IsNullOrEmpty(environmentName))
        {
            throw new ArgumentNullException(nameof(environmentName));
        }

        if (string.IsNullOrEmpty(versionLabel))
        {
            throw new ArgumentNullException(nameof(versionLabel));
        }

        var client = GetClient(settings);
        var status = client.DescribeEnvironmentsAsync(new DescribeEnvironmentsRequest
        {
            ApplicationName = applicationName,
            EnvironmentNames = new List<string>(new[] {environmentName}),
            VersionLabel = versionLabel,
            IncludeDeleted = false,
        }).Result.Environments[0].Status.Value;

        return status == "Ready";
    }
}

这是完整的异常消息:

System.AggregateException: One or more errors occurred. ---> System.MissingMethodException: Method not found: 'System.String Amazon.Runtime.Internal.Util.StringUtils.FromDateTimeToISO8601(System.DateTime)'. at Amazon.ElasticBeanstalk.Model.Internal.MarshallTransformations.DescribeEnvironmentsRequestMarshaller.Marshall(DescribeEnvironmentsRequest publicRequest) at Amazon.Runtime.Internal.Marshaller.PreInvoke(IExecutionContext executionContext) at Amazon.Runtime.Internal.Marshaller.InvokeAsync[T](IExecutionContext executionContext) at Amazon.Runtime.Internal.CallbackHandler.d__91.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Amazon.Runtime.Internal.ErrorCallbackHandler.<InvokeAsync>d__51.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Amazon.Runtime.Internal.MetricsHandler.d__11.MoveNext() --- End of inner exception stack trace --- at System.Threading.Tasks.Task1.GetResultCore(Boolean waitCompletionNotification) at Cake.AWS.ElasticBeanstalk.ElasticBeanstalkManager.ApplicationVersionReady(ElasticBeanstalkSettings settings, String applicationName, String environmentName, String versionLabel) at Submission#0.<>b__0_11(ICakeContext context) ---> (Inner Exception #0) System.MissingMethodException: Method not found: 'System.String Amazon.Runtime.Internal.Util.StringUtils.FromDateTimeToISO8601(System.DateTime)'. at Amazon.ElasticBeanstalk.Model.Internal.MarshallTransformations.DescribeEnvironmentsRequestMarshaller.Marshall(DescribeEnvironmentsRequest publicRequest) at Amazon.Runtime.Internal.Marshaller.PreInvoke(IExecutionContext executionContext) at Amazon.Runtime.Internal.Marshaller.InvokeAsync[T](IExecutionContext executionContext) at Amazon.Runtime.Internal.CallbackHandler.d__91.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Amazon.Runtime.Internal.ErrorCallbackHandler.<InvokeAsync>d__51.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Amazon.Runtime.Internal.MetricsHandler.d__1`1.MoveNext()<---

我的猜测是蛋糕上下文在某处设置请求的日期时间,这是亚马逊无法处理的格式。如果有人有任何想法或遇到过类似的问题,我将不胜感激。

我的猜测是,您缺少一些依赖项。

如错误所述,无法找到方法 Amazon.Runtime.Internal.Util.StringUtils.FromDateTimeToISO8601(System.DateTime)。查看 Cake addin you mentioned, on nuget.org it shows that it has some dependencies to the AWSSDK.Core and AWSSDK.ElasticBeanstalk packages. And on the github project of the first one you can see, that this is where the method is implemented.

所以我猜你在构建你的分叉插件时没有指定这些依赖项,因此发生了错误。如果您构建一个 nuget 包,请将这些包添加为依赖项(与原始插件的方式相同)。

我想通了这个问题。我使用了两个插件,第一个是 Cake.AWS.S3,第二个是 Cake.AWS.ElasticBeanstalk,因为当蛋糕需要引用 AWSSDK.Core.dll 时首先定义了 S3 插件,它将使用 S3 插件提供的 .dll这恰好是一个比 ElasticBeanstalk 插件预期的版本更旧的版本,导致它调用了一个不存在的方法。

如果我先简单地定义 Cake.AWS.ElasticBeanstalk 插件,它就可以工作。我可能会提交一个拉取请求来升级 S3 插件的 AWSSDK.Core.dll