2015-04-06 38 views
5

Używamy Gitlab.com jako naszego centralnego repozytorium GIT. W ten sam sposób, aby wdrożyć aplikację w AWS Elastic Beanstalk, należy ją przesłać za pomocą git aws.push, w tle wykonać normalny git push na Amazon. Chcę sposób, aby popchnąć do gitlab i Gitlab zrobić push do Elastic Beanstalk. Wiem o aliasie git, używając go jestem w stanie wykonać git push i git aws.push za pomocą jednego polecenia, ale czego chcę to push tylko do gitlab i od gitlab do AWS.Haczyk lub coś w Gitlab, aby zrobić git aws.push do AWS Elastic Beanstalk

Zastanawiam się w Gitlab Web Hooks, może niektóre już przetłumaczyć to na PHP lub jakiś język serwera w celu implementacji Web Hook? lub jakiekolwiek inne rozwiązanie do wdrożenia z Gitlab do AWS Elastic Beanstalk.

Jest kod w Elektrowni Shell wykorzystywane przez git aws.push zrobić push git do Elastic Beanstalk:

$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 
} 

Odpowiedz

0

Pierwszy Określ AWS_ACCESS_KEY_ID i AWS_SECRET_ACCESS_KEY w gitlab: https://gitlab.com/snw/<project_name>/settings/ci_cd

następnie dodać .gitlab-ci.yml plik do katalogu głównego Twojego 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 

Rekwizyty do: