2015-04-06 5 views
5

Wir verwenden Gitlab.com als unsere zentrale GIT Repo. Auf die gleiche Weise, um die App auf AWS Elastic Beanstalk zu implementieren, wird es mit git aws.push geschoben, es im Hintergrund tun eine normale git push zu Amazon. Ich möchte einen Weg, um zu gitlab und Gitlab Push an Elastic Beanstalk schieben. Ich weiß über Git Alias, ich benutze es, ich kann git push und git aws.push mit einem Befehl ausführen, aber was ich will, ist Push nur zu gitlab und von gitlab zu AWS.Hook oder etwas in Gitlab, um ein Git zu machen aws.push zu AWS Elastic Beanstalk

Ich denke in Gitlab Web Hooks, vielleicht einige bereits in PHP oder einige Serversprache übersetzen, um den Web Hook zu implementieren? oder eine andere Lösung für die Bereitstellung von Gitlab auf AWS Elastic Beanstalk.

der Code gibt in Power Shell von git aws.push verwendet wird, ist ein Git Push-to-Elastic Beanstalk zu tun:

$awsSource = @" 
using System; 
using System.Globalization; 
using System.Text; 
using System.Security.Cryptography; 

namespace Amazon.DevTools 
{ 
    public class AWSUser 
    { 
     public string AccessKey 
     { 
      get; 
      set; 
     } 

     public string SecretKey 
     { 
      get; 
      set; 
     } 

     protected internal void Validate() 
     { 
      if (string.IsNullOrEmpty(this.AccessKey)) 
      { 
       throw new InvalidOperationException("[AccessKey]"); 
      } 
      if (string.IsNullOrEmpty(this.SecretKey)) 
      { 
       throw new InvalidOperationException("[SecretKey]"); 
      } 
     } 
    } 
} 

namespace Amazon.DevTools 
{ 
    public abstract class AWSDevToolsRequest 
    { 
     protected const string METHOD = "GIT"; 
     protected const string SERVICE = "devtools"; 

     DateTime dateTime; 

     public AWSDevToolsRequest() 
      : this(DateTime.UtcNow) 
     { 
     } 

     public AWSDevToolsRequest(DateTime dateTime) 
     { 
      if (dateTime == null) 
      { 
       throw new ArgumentNullException("dateTime"); 
      } 
      this.dateTime = dateTime.ToUniversalTime(); 
     } 

     public string DateStamp 
     { 
      get 
      { 
       return this.dateTime.ToString("yyyyMMdd", CultureInfo.InvariantCulture); 
      } 
     } 

     public string DateTimeStamp 
     { 
      get 
      { 
       return this.dateTime.ToString("yyyyMMddTHHmmss", CultureInfo.InvariantCulture); 
      } 
     } 

     public abstract string DerivePath(); 

     protected internal abstract string DeriveRequest(); 

     public string Host 
     { 
      get; 
      set; 
     } 

     public string Region 
     { 
      get; 
      set; 
     } 

     public string Service 
     { 
      get 
      { 
       return AWSDevToolsRequest.SERVICE; 
      } 
     } 

     protected internal virtual void Validate() 
     { 
      if (string.IsNullOrEmpty(this.Host)) 
      { 
       throw new InvalidOperationException("[Host]"); 
      } 
      if (string.IsNullOrEmpty(this.Region)) 
      { 
       throw new InvalidOperationException("[Region]"); 
      } 
     } 
    } 
} 

namespace Amazon.DevTools 
{ 
    public class AWSElasticBeanstalkRequest : AWSDevToolsRequest 
    { 
     public AWSElasticBeanstalkRequest() 
      : base() 
     { 
     } 

     public AWSElasticBeanstalkRequest(DateTime dateTime) 
      : base(dateTime) 
     { 
     } 

     public string Application 
     { 
      get; 
      set; 
     } 

     public override string DerivePath() 
     { 
      this.Validate(); 

      string path = null; 

      if (string.IsNullOrEmpty(this.Environment)) 
      { 
       path = string.Format("/v1/repos/{0}/commitid/{1}" 
     , this.Encode(this.Application) 
     , this.Encode(this.CommitId)); 
      } 
      else 
      { 
       path = string.Format("/v1/repos/{0}/commitid/{1}/environment/{2}" 
     , this.Encode(this.Application) 
     , this.Encode(this.CommitId) 
     , this.Encode(this.Environment)); 
      } 
      return path; 
     } 

     protected internal override string DeriveRequest() 
     { 
      this.Validate(); 

      string path = this.DerivePath(); 
      string request = string.Format("{0}\n{1}\n\nhost:{2}\n\nhost\n", AWSDevToolsRequest.METHOD, path, this.Host); 
      return request; 
     } 

     public string Environment 
     { 
      get; 
      set; 
     } 

    public string CommitId 
    { 
     get; 
     set; 
    } 

     protected internal override void Validate() 
     { 
      base.Validate(); 
      if (string.IsNullOrEmpty(this.Application)) 
      { 
       throw new InvalidOperationException("[Application]"); 
      } 
      if (string.IsNullOrEmpty(this.Host)) 
      { 
       throw new InvalidOperationException("[Host]"); 
      } 
     } 

    protected internal string Encode(string plaintext) 
    { 
     StringBuilder sb = new StringBuilder(); 
     foreach (byte b in new UTF8Encoding().GetBytes(plaintext)) 
     { 
     sb.Append(b.ToString("x2", CultureInfo.InvariantCulture)); 
     } 
     return sb.ToString(); 
    } 

    } 
} 

namespace Amazon.DevTools 
{ 
    public class AWSDevToolsAuth 
    { 
     const string AWS_ALGORITHM = "HMAC-SHA256"; 
     const string HASH_ALGORITHM = "SHA-256"; 
     const string HMAC_ALGORITHM = "HMACSHA256"; 
     const string SCHEME = "AWS4"; 
     const string TERMINATOR = "aws4_request"; 

     AWSUser user; 
     AWSDevToolsRequest request; 

     public AWSDevToolsAuth(AWSUser user, AWSDevToolsRequest request) 
     { 
      this.user = user; 
      this.request = request; 
     } 

     static byte[] DeriveKey(AWSUser user, AWSDevToolsRequest request) 
     { 
      string secret = string.Format("{0}{1}", AWSDevToolsAuth.SCHEME, user.SecretKey); 
      byte[] kSecret = Encoding.UTF8.GetBytes(secret); 
      byte[] kDate = AWSDevToolsAuth.Hash(AWSDevToolsAuth.HMAC_ALGORITHM, kSecret, Encoding.UTF8.GetBytes(request.DateStamp)); 
      byte[] kRegion = AWSDevToolsAuth.Hash(AWSDevToolsAuth.HMAC_ALGORITHM, kDate, Encoding.UTF8.GetBytes(request.Region)); 
      byte[] kService = AWSDevToolsAuth.Hash(AWSDevToolsAuth.HMAC_ALGORITHM, kRegion, Encoding.UTF8.GetBytes(request.Service)); 
      byte[] key = AWSDevToolsAuth.Hash(AWSDevToolsAuth.HMAC_ALGORITHM, kService, Encoding.UTF8.GetBytes(AWSDevToolsAuth.TERMINATOR)); 
      return key; 
     } 

     public string DerivePassword() 
     { 
      this.user.Validate(); 
      this.request.Validate(); 

      string signature = AWSDevToolsAuth.SignRequest(this.user, this.request); 
      string password = string.Format("{0}Z{1}", this.request.DateTimeStamp, signature); 
      return password; 
     } 

     public Uri DeriveRemote() 
     { 
      this.request.Validate(); 

      string path = this.request.DerivePath(); 
      string password = this.DerivePassword(); 
      string username = this.DeriveUserName(); 
      UriBuilder remote = new UriBuilder() 
      { 
       Host = this.request.Host, 
       Path = path, 
       Password = password, 
       Scheme = "https", 
       UserName = username, 
      }; 
      return remote.Uri; 
     } 

     public string DeriveUserName() 
     { 
      this.user.Validate(); 

      return this.user.AccessKey; 
     } 

     static byte[] Hash(string algorithm, byte[] message) 
     { 
      HashAlgorithm hash = HashAlgorithm.Create(algorithm); 
      byte[] digest = hash.ComputeHash(message); 
      return digest; 
     } 

     static byte[] Hash(string algorithm, byte[] key, byte[] message) 
     { 
      KeyedHashAlgorithm hash = KeyedHashAlgorithm.Create(algorithm); 
      hash.Key = key; 
      byte[] digest = hash.ComputeHash(message); 
      return digest; 
     } 

     static string SignRequest(AWSUser user, AWSDevToolsRequest request) 
     { 
      string scope = string.Format("{0}/{1}/{2}/{3}", request.DateStamp, request.Region, request.Service, AWSDevToolsAuth.TERMINATOR); 
      StringBuilder stringToSign = new StringBuilder(); 
      stringToSign.AppendFormat("{0}-{1}\n{2}\n{3}\n", AWSDevToolsAuth.SCHEME, AWSDevToolsAuth.AWS_ALGORITHM, request.DateTimeStamp, scope); 
      byte[] requestBytes = Encoding.UTF8.GetBytes(request.DeriveRequest()); 
      byte[] requestDigest = AWSDevToolsAuth.Hash(AWSDevToolsAuth.HASH_ALGORITHM, requestBytes); 
      stringToSign.Append(AWSDevToolsAuth.ToHex(requestDigest)); 
      byte[] key = AWSDevToolsAuth.DeriveKey(user, request); 
      byte[] digest = AWSDevToolsAuth.Hash(AWSDevToolsAuth.HMAC_ALGORITHM, key, Encoding.UTF8.GetBytes(stringToSign.ToString())); 
      string signature = AWSDevToolsAuth.ToHex(digest); 
      return signature; 
     } 

     static string ToHex(byte[] data) 
     { 
      StringBuilder hex = new StringBuilder(); 
      foreach (byte b in data) 
      { 
       hex.Append(b.ToString("x2", CultureInfo.InvariantCulture)); 
      } 
      return hex.ToString(); 
     } 
    } 
} 

"@ 

Add-Type -Language CSharpVersion3 -TypeDefinition $awsSource 

# -*-powershell-*- 

# 
# Sets the AWS.push configuration values 
# 
# Will read values from the pipeline input if none are present the values are read from the console input instead. 
# 
function Edit-AWSElasticBeanstalkRemote 
{ 
    [email protected]($input) 
    $used=0 

    $config = Read-Config $False $True 
    $awsAccessKey = Lookup-Setting $config "global" "AWSAccessKeyId" ("cred","git") 
    if (!$awsAccessKey -and (ShouldWrite-Credentials $config $false)) 
    { 
     $awsAccessKeyInput = ($data[$used++] | Input-Data "AWS Access Key") 
    } 
    if ($awsAccessKeyInput) 
    { 
     $config = Write-Setting $config "cred" "global" "AWSAccessKeyId" $awsAccessKeyInput 
    } 

    $awsSecretKey = Lookup-Setting $config "global" "AWSSecretKey" ("cred","git") 
    if (!$awsSecretKey -and (ShouldWrite-Credentials $config $false)) 
    { 
     $awsSecretKeyInput = ($data[$used++] | Input-Data "AWS Secret Key") 
    } 
    if ($awsSecretKeyInput) 
    { 
     $config = Write-Setting $config "cred" "global" "AWSSecretKey" $awsSecretKeyInput 
    } 

    $awsRegion = Lookup-Setting $config "global" "Region" ("eb","git") 
    if (-not $awsRegion) 
    { 
     $awsRegion = "us-east-1" 
     $config = Write-Setting $config "eb" "global" "Region" $awsRegion 
    } 
    $awsRegionInput = ($data[$used++] | Input-Data "AWS Region [default to $($awsRegion)]") 
    if ($awsRegionInput) 
    { 
    $awsRegion = $awsRegionInput 
     $config = Write-Setting $config "eb" "global" "Region" $awsRegionInput 
    } 

    $awsHost = Get-Endpoint $awsRegion 
    if ($awsHost) 
    { 
     $config = Write-Setting $config "eb" "global" "DevToolsEndpoint" $awsHost 
    } 
    else 
    { 
     $awsHostInput = ($data[$used++] | Input-Data "AWS Host [default to git.elasticbeanstalk.us-east-1.amazonaws.com]") 

     if ($awsHostInput) 
     { 
      $config = Write-Setting $config "eb" "global" "DevToolsEndpoint" $awsHostInput 
     } 
     else 
     { 
      $config = Write-Setting $config "eb" "global" "DevToolsEndpoint" "git.elasticbeanstalk.us-east-1.amazonaws.com" 
     } 
    } 

    $awsApplication = Lookup-Setting $config "global" "ApplicationName" ("eb","git") 
    if ($awsApplication) 
    { 
     $awsApplicationInput = ($data[$used++] | Input-Data "AWS Elastic Beanstalk Application [default to $($awsApplication)]") 
    } 
    else 
    { 
     $awsApplicationInput = ($data[$used++] | Input-Data "AWS Elastic Beanstalk Application") 
    } 
    if ($awsApplicationInput) 
    { 
     $config = Write-Setting $config "eb" "global" "ApplicationName" $awsApplicationInput 
    } 

    $awsEnvironment = Lookup-Setting $config "global" "EnvironmentName" ("eb","git") 
    if ($awsEnvironment) 
    { 
     $awsEnvironmentInput = ($data[$used++] | Input-Data "AWS Elastic Beanstalk Environment [default to $($awsEnvironment)]") 
    } 
    else 
    { 
     $awsEnvironmentInput = ($data[$used++] | Input-Data "AWS Elastic Beanstalk Environment") 
    } 
    if ($awsEnvironmentInput) 
    { 
     $config = Write-Setting $config "eb" "global" "EnvironmentName" $awsEnvironmentInput 
    } 

    Write-Config $config 
} 

# 
# Looks up the endpoint for a region 
# 
# @params $region 
# @return The endpoint 
# 
function Get-Endpoint 
{ 
    Param($region) 
    switch ($region) 
    { 
     "us-east-1" { $endpoint = "git.elasticbeanstalk.us-east-1.amazonaws.com" } 
     "ap-northeast-1" { $endpoint = "git.elasticbeanstalk.ap-northeast-1.amazonaws.com" } 
     "ap-southeast-1" { $endpoint = "git.elasticbeanstalk.ap-southeast-1.amazonaws.com" } 
     "ap-southeast-2" { $endpoint = "git.elasticbeanstalk.ap-southeast-2.amazonaws.com" } 
     "eu-west-1" { $endpoint = "git.elasticbeanstalk.eu-west-1.amazonaws.com" } 
     "sa-east-1" { $endpoint = "git.elasticbeanstalk.sa-east-1.amazonaws.com" } 
     "us-west-1" { $endpoint = "git.elasticbeanstalk.us-west-1.amazonaws.com" } 
     "us-west-2" { $endpoint = "git.elasticbeanstalk.us-west-2.amazonaws.com" } 
    } 
    $endpoint 
} 
# 
# Gets the remote URL used for AWS.push 
# 
# @param $e environment that is deployed too. 
# @param $c commit to deploy 
# @return The URL 
# 
function Get-AWSElasticBeanstalkRemote 
{ 
    Param([string] $e, 
      [string] $c, 
      [bool] $toPush = $FALSE) 
    trap [System.Management.Automation.MethodInvocationException] 
    { 
     if ($_.Exception -and $_.Exception.InnerException) 
     { 
      $awsOption = $_.Exception.InnerException.Message 
      switch ($awsOption) 
      { 
       "[AccessKey]" { $awsOption = "aws.accesskey" } 
       "[Application]" { $awsOption = "aws.elasticbeanstalk.application" } 
       "[Host]" { $awsOption = "aws.elasticbeanstalk.host" } 
       "[Region]" { $awsOption = "aws.region" } 
       "[SecretKey]" { $awsOption = "aws.secretkey" } 
      } 
      Write-Host "Missing configuration setting for: $($awsOption)" 
     } 
     else 
     { 
      Write-Host "An unknown error occurred while computing your temporary password." 
     } 
     Write-Host "`nTry running 'git aws.config' to update your repository configuration." 
     Exit 
    } 

    $config = Read-Config 
    $awsAccessKey = Lookup-Setting $config "global" "AWSAccessKeyId" ("cred","git") 
    $awsSecretKey = Lookup-Setting $config "global" "AWSSecretKey" ("cred","git") 
    $awsRegion = Lookup-Setting $config "global" "Region" ("eb","git") 
    $awsHost = Lookup-Setting $config "global" "DevToolsEndpoint" ("eb","git") 
    $awsApplication = Lookup-Setting $config "global" "ApplicationName" ("eb","git") 

    if ($e) 
    { 
     $awsEnvironment = $e 
    } 
    else 
    { 
     $branchName = &git rev-parse --abbrev-ref HEAD 
     $defaultEnv = Lookup-Setting $config "branches" $branchName ("eb") 
     if ($defaultEnv) 
     { 
     $awsEnvironment = $defaultEnv 
     } 
     else 
     { 
     $awsEnvironment = Lookup-Setting $config "global" "EnvironmentName" ("eb","git") 
     } 
    } 

    $gitCommitId = $c 

    $awsUser = New-Object -TypeName Amazon.DevTools.AWSUser 
    $awsUser.AccessKey = $awsAccessKey 
    $awsUser.SecretKey = $awsSecretKey 

    $awsRequest = New-Object -TypeName Amazon.DevTools.AWSElasticBeanstalkRequest 
    $awsRequest.Region = $awsRegion 
    $awsRequest.Host = $awsHost 
    $awsRequest.Application = $awsApplication 
    $awsRequest.Environment = $awsEnvironment 
    $awsRequest.CommitId = $gitCommitId 

    $awsAuth = New-Object -TypeName Amazon.DevTools.AWSDevToolsAuth $awsUser,$awsRequest 
    $awsRemote = $awsAuth.DeriveRemote() 
    if($toPush) { 
     Write-Host "Pushing to environment: $awsEnvironment" 
    } 
    return $awsRemote.ToString() 
} 

# 
# Performs the aws.push 
# 
# @param $e environment that is deployed too. 
# @param $c commit to deploy 
# 
function Invoke-AWSElasticBeanstalkPush 
{ 
    Param([string] $e, [string] $c) 
    $remote = Get-AWSElasticBeanstalkRemote $e $c $TRUE 
    $src = $c 
    $dst = "refs/heads/master" 
    $commit = $src + ":" + $dst 
    &git push -f $remote $commit 
} 

# 
# Adds the git aliases for aws.push and aws.config to the git repository. 
# 
function Initialize-AWSElasticBeanstalkRepository 
{ 
    $command = 'Import-Module AWSDevTools; $e, $c = Get-Options $args; Get-AWSElasticBeanstalkRemote $e $c' 
    &git config alias.aws.elasticbeanstalk.remote "!powershell -noprofile -executionpolicy bypass -command '& { $command }'" 

    $command = 'Import-Module AWSDevTools; $e, $c = Get-Options $args; Invoke-AWSElasticBeanstalkPush $e $c' 
    &git config alias.aws.push "!powershell -noprofile -executionpolicy bypass -command '& { $command }'" 

    $command = 'Import-Module AWSDevTools; Edit-AWSElasticBeanstalkRemote' 
    &git config alias.aws.config "!powershell -noprofile -executionpolicy bypass -command '& { $command }'" 
} 

# 
# Read in data 
# 
# Will used pipeline data if present, otherwise reads from the console 
# 
# @param $message The text to display as a prompt 
# @return The data collected 
# 
function Input-Data 
{ 
    Param([string] $message) 
    Write-Host -NoNewline "$($message): " 
    if (($input.MoveNext()) -and ($input.Current)) 
    { 
     Write-Host $input.Current 
     $input.Current 
    } 
    else 
    { 
     [Console]::In.ReadLine() 
    } 
} 

# 
# Gets the values for the aws.push and aws.config command options 
# 
# @param $arr The command line options passed to the command 
# @return The options values 
# 
function Get-Options 
{ 
    Param([string[]] $arr) 

    $e = $null; 
    $c = $null; 

    $optionmappings = @{ 
     '--environment' = 'environment'; 
     '-e' = 'environment'; 
     '--commit' = 'commit'; 
     '-c' = 'commit'; 
     '--help' = 'help'; 
     '-h' = 'help' 
    } 

    $options = @{} 

    for ($i=0; $i -lt $arr.count; $i++) 
    { 
     $optname = $arr[$i] 
     $mappedoption = $optionmappings[$optname] 
     if (!$mappedoption) { 
      Write-Host("Unknown Option: {0}" -f $arr[$i]) 
      Write-Help 
      Exit 
     } 
     if ($mappedoption -eq "help") { 
      Write-Help 
      Exit 
     } 

     $value = $arr[++$i] 
     if (($value -eq $null) -or $optionmappings[$value]) { 
      Write-Host("You must provide a value for {0}" -f $optname) 
      Write-Help 
      Exit 
     } 
     if ($options[$mappedoption]) { 
      Write-Host("--{0} specified twice" -f $mappedoption) 
      Exit 
     } 
     $options[$mappedoption] = $value 
    } 

    $e = $options["environment"] 
    $c = $options["commit"] 

    if ($c -eq $null) { 
     $c = "HEAD" 
    } 
    $c = Parse-CommitOption $c 
    $result = $e, $c 
    $result 
} 

Antwort

0

Sie zuerst Ihre AWS_ACCESS_KEY_ID und AWS_SECRET_ACCESS_KEY in Gitlab: https://gitlab.com/snw/<project_name>/settings/ci_cd

Dann wird ein hinzufügen .gitlab-ci.yml Datei auf Ihrer root-Repo:

variables: 
    ARCHIVE_NAME: "archive.zip" 
    ARCHIVE_LOCATION: "deployments/" 
    S3_BUCKET_NAME: "my-deployments" 
    ELASTIC_BEANSTALK_APP_NAME: "myAppName" 
    AWS_REGION: "us-east-1" 

elastic_beanstalk_deploy: 
    image: python:latest 
    script: 
    - apt-get update --assume-yes 
    - apt-get install zip --assume-yes 
    - zip -r $ARCHIVE_LOCATION$ARCHIVE_NAME . 
    - pip install awscli 
    - aws s3 cp $ARCHIVE_LOCATION$ARCHIVE_NAME s3://$S3_BUCKET_NAME/ 
    - aws elasticbeanstalk create-application-version --application-name $ELASTIC_BEANSTALK_APP_NAME --version-label `date "+%Y%m%d-%H%M%S"` --description "$(git log -1 --pretty=%B)" --source-bundle S3Bucket="$S3_BUCKET_NAME",S3Key="$ARCHIVE_NAME" --region $AWS_REGION 

Props an:

Verwandte Themen