From 809ea6f700c5c55f1633944ffd90503682516915 Mon Sep 17 00:00:00 2001 From: Sergey Murashov Date: Thu, 3 Apr 2014 18:49:01 +0400 Subject: [PATCH] Changed tests for murano repository Change base methods for actions with packages and add tests for this actions Change-Id: Ib6af8933c18ea9670a388dca53f1c55a92180208 --- functionaltests/api/base.py | 41 ++- .../v1/DummyTestApp/Classes/Controller.yaml | 19 ++ .../v1/DummyTestApp/Classes/DomainHost.yaml | 20 ++ .../api/v1/DummyTestApp/Classes/Dummy.yaml | 37 +++ .../api/v1/DummyTestApp/Classes/Host.yaml | 49 ++++ .../Classes/PrimaryController.yaml | 33 +++ .../Classes/SecondaryController.yaml | 28 ++ .../DummyTestApp/Resources/AskDnsIp.template | 12 + .../Resources/CreatePrimaryDC.template | 16 + .../Resources/CreateSecondaryDC.template | 18 ++ .../Resources/JoinDomain.template | 25 ++ .../Resources/SetPassword.template | 17 ++ .../scripts/Get-DnsListeningIpAddress.ps1 | 7 + .../Resources/scripts/ImportCoreFunctions.ps1 | 68 +++++ .../Install-RolePrimaryDomainController.ps1 | 43 +++ .../Install-RoleSecondaryDomainController.ps1 | 69 +++++ .../Resources/scripts/Join-Domain.ps1 | 67 +++++ .../scripts/Set-LocalUserPassword.ps1 | 37 +++ .../api/v1/DummyTestApp/UI/ui.yaml | 165 +++++++++++ functionaltests/api/v1/DummyTestApp/logo2.png | Bin 0 -> 11634 bytes .../api/v1/DummyTestApp/manifest.yaml | 26 ++ functionaltests/api/v1/test_repository.py | 273 ++++++++++++++---- functionaltests/run_tests.sh | 2 +- 23 files changed, 1001 insertions(+), 71 deletions(-) create mode 100644 functionaltests/api/v1/DummyTestApp/Classes/Controller.yaml create mode 100644 functionaltests/api/v1/DummyTestApp/Classes/DomainHost.yaml create mode 100644 functionaltests/api/v1/DummyTestApp/Classes/Dummy.yaml create mode 100644 functionaltests/api/v1/DummyTestApp/Classes/Host.yaml create mode 100644 functionaltests/api/v1/DummyTestApp/Classes/PrimaryController.yaml create mode 100644 functionaltests/api/v1/DummyTestApp/Classes/SecondaryController.yaml create mode 100644 functionaltests/api/v1/DummyTestApp/Resources/AskDnsIp.template create mode 100644 functionaltests/api/v1/DummyTestApp/Resources/CreatePrimaryDC.template create mode 100644 functionaltests/api/v1/DummyTestApp/Resources/CreateSecondaryDC.template create mode 100644 functionaltests/api/v1/DummyTestApp/Resources/JoinDomain.template create mode 100644 functionaltests/api/v1/DummyTestApp/Resources/SetPassword.template create mode 100644 functionaltests/api/v1/DummyTestApp/Resources/scripts/Get-DnsListeningIpAddress.ps1 create mode 100644 functionaltests/api/v1/DummyTestApp/Resources/scripts/ImportCoreFunctions.ps1 create mode 100644 functionaltests/api/v1/DummyTestApp/Resources/scripts/Install-RolePrimaryDomainController.ps1 create mode 100644 functionaltests/api/v1/DummyTestApp/Resources/scripts/Install-RoleSecondaryDomainController.ps1 create mode 100644 functionaltests/api/v1/DummyTestApp/Resources/scripts/Join-Domain.ps1 create mode 100644 functionaltests/api/v1/DummyTestApp/Resources/scripts/Set-LocalUserPassword.ps1 create mode 100644 functionaltests/api/v1/DummyTestApp/UI/ui.yaml create mode 100644 functionaltests/api/v1/DummyTestApp/logo2.png create mode 100644 functionaltests/api/v1/DummyTestApp/manifest.yaml diff --git a/functionaltests/api/base.py b/functionaltests/api/base.py index fa6a21c6..2f2d7f52 100644 --- a/functionaltests/api/base.py +++ b/functionaltests/api/base.py @@ -13,12 +13,15 @@ # under the License. import json +import os +import requests +import testtools +import uuid + from tempest import clients from tempest.common import rest_client from tempest import config from tempest import exceptions -import testtools -import uuid CONF = config.CONF @@ -142,16 +145,32 @@ class MuranoClient(rest_client.RestClient): return resp, json.loads(body) - def update_package(self, id): - post_body = [ - { - "op": "add", - "path": "/tags", - "value": ["i'm a test"] - } - ] + def upload_package(self, package_name, body): + __location__ = os.path.realpath(os.path.join( + os.getcwd(), os.path.dirname(__file__))) - resp, body = self.patch('catalog/packages/{0}'.format(id), post_body) + headers = {'X-Auth-Token': self.auth_provider.get_token()} + + files = {'%s' % package_name: open( + os.path.join(__location__, 'v1/DummyTestApp.zip'), 'rb')} + + post_body = {'JsonString': json.dumps(body)} + request_url = '{endpoint}{url}'.format(endpoint=self.base_url, + url='/catalog/packages') + + resp = requests.post(request_url, files=files, data=post_body, + headers=headers) + + return resp + + def update_package(self, id, post_body): + headers = { + 'X-Auth-Token': self.auth_provider.get_token(), + 'content-type': 'application/murano-packages-json-patch' + } + + resp, body = self.patch('catalog/packages/{0}'.format(id), + json.dumps(post_body), headers=headers) return resp, json.loads(body) diff --git a/functionaltests/api/v1/DummyTestApp/Classes/Controller.yaml b/functionaltests/api/v1/DummyTestApp/Classes/Controller.yaml new file mode 100644 index 00000000..b1eadcb5 --- /dev/null +++ b/functionaltests/api/v1/DummyTestApp/Classes/Controller.yaml @@ -0,0 +1,19 @@ +Namespaces: + =: io.murano.windows.Dummy + std: io.murano + sys: io.murano.system + win: io.murano.windows + +Name: Controller + +Properties: + host: + Contract: $.class(win:Host).notNull() + + recoveryPassword: + Contract: $.string().notNull() + Default: P@ssw0rd + +Workflow: + deploy: + Body: $.host.deploy() diff --git a/functionaltests/api/v1/DummyTestApp/Classes/DomainHost.yaml b/functionaltests/api/v1/DummyTestApp/Classes/DomainHost.yaml new file mode 100644 index 00000000..68706f4a --- /dev/null +++ b/functionaltests/api/v1/DummyTestApp/Classes/DomainHost.yaml @@ -0,0 +1,20 @@ +Namespaces: + =: io.murano.windows + ad: io.murano.windows.Dummy + +Name: DomainHost + +Extends: Host + +Properties: + domain: + Contract: $.class(ad:Dummy).notNull() + +Workflow: + deploy: + Arguments: + Body: + - $.super($.deploy()) + #- $.joinDomain($.domain) + # Workaround against broken ResourceManager: + - $.super($.joinDomain($this.domain)) diff --git a/functionaltests/api/v1/DummyTestApp/Classes/Dummy.yaml b/functionaltests/api/v1/DummyTestApp/Classes/Dummy.yaml new file mode 100644 index 00000000..0f3d7859 --- /dev/null +++ b/functionaltests/api/v1/DummyTestApp/Classes/Dummy.yaml @@ -0,0 +1,37 @@ +Namespaces: + =: io.murano.windows.Dummy + std: io.murano + sys: io.murano.system + +Name: Dummy + +Extends: std:Application + +Properties: + name: + Contract: $.string().notNull() + + primaryController: + Contract: $.class(PrimaryController).notNull() + + secondaryControllers: + Contract: [$.class(SecondaryController).notNull()] + + adminAccountName: + Contract: $.string().notNull() + Default: Administrator + + adminPassword: + Contract: $.string().notNull() + Default: P@ssw0rd + +Workflow: + deploy: + Body: + - $.primaryController.deploy() + - $.secondaryControllers.pselect($.deploy()) + - $.reportDeployed(title => 'Dummy', + unitCount => len(secondaryControllers) + 1) + + destroy: + - $.reportDestroyed() diff --git a/functionaltests/api/v1/DummyTestApp/Classes/Host.yaml b/functionaltests/api/v1/DummyTestApp/Classes/Host.yaml new file mode 100644 index 00000000..88be1953 --- /dev/null +++ b/functionaltests/api/v1/DummyTestApp/Classes/Host.yaml @@ -0,0 +1,49 @@ +Namespaces: + =: io.murano.windows + ad: io.murano.windows.Dummy + res: io.murano.resources + sys: io.murano.system + +Name: Host + +Extends: res:Instance + +Properties: + adminAccountName: + Contract: $.string().notNull() + Default: Administrator + + adminPassword: + Contract: $.string().notNull() + +Workflow: + initialize: + Body: + - $.super($.initialize()) + + deploy: + Body: + - $.super($.deploy()) + + - $resources: new(sys:Resources) + - $template: $resources.json('SetPassword.template').bind(dict( + adminPassword => $.adminPassword + )) + - $.agent.send($template, $resources) + + joinDomain: + Arguments: + - domain: + Contract: $.class(ad:Dummy).notNull() + Body: + + - $resources: new(sys:Resources) + - $template: $resources.json('JoinDomain.template').bind(dict( + domain => $domain.name, + domainUser => $domain.adminAccountName, + domainPassword => $domain.adminPassword, + ouPath => '', + dnsIp => $domain.primaryController.dnsIp + )) + - $.agent.call($template, $resources) + diff --git a/functionaltests/api/v1/DummyTestApp/Classes/PrimaryController.yaml b/functionaltests/api/v1/DummyTestApp/Classes/PrimaryController.yaml new file mode 100644 index 00000000..5bae8a50 --- /dev/null +++ b/functionaltests/api/v1/DummyTestApp/Classes/PrimaryController.yaml @@ -0,0 +1,33 @@ +Namespaces: + =: io.murano.windows.Dummy + std: io.murano + sys: io.murano.system + +Name: PrimaryController + +Extends: Controller + +Properties: + + dnsIp: + Contract: $.string() + +Workflow: + initialize: + Body: + - $.super($.initialize()) + - $.domain: $.find(Dummy).require() + + deploy: + Arguments: + Body: + - $.super($.deploy()) + - $resources: new(io.murano.system.Resources) + - $template: $resources.json('CreatePrimaryDC.template').bind(dict( + domain => $.domain.name, + recoveryPassword => $.recoveryPassword + )) + - $.host.agent.call($template, $resources) + + - $template: $resources.json('AskDnsIp.template') + - $.dnsIp: $.host.agent.call($template, $resources)[0] diff --git a/functionaltests/api/v1/DummyTestApp/Classes/SecondaryController.yaml b/functionaltests/api/v1/DummyTestApp/Classes/SecondaryController.yaml new file mode 100644 index 00000000..ff9eee20 --- /dev/null +++ b/functionaltests/api/v1/DummyTestApp/Classes/SecondaryController.yaml @@ -0,0 +1,28 @@ +Namespaces: + =: io.murano.windows.Dummy + std: io.murano + sys: io.murano.system + +Name: SecondaryController + +Extends: Controller + +Workflow: + initialize: + Body: + - $.super($.initialize()) + - $.domain: $.find(ActiveDirectory).require() + + deploy: + Body: + - $.super($.deploy()) + - $.host.joinDomain($.domain) + - $resources: new(sys:Resources) + - $template: $resources.json('CreateSecondaryDC.template').bind(dict( + domain => $.domain.name, + recoveryPassword => $.recoveryPassword, + domainAccountName => $.domain.adminAccountName, + domainPassword => $.domain.adminPassword + )) + - $.host.agent.call($template, $resources) +# diff --git a/functionaltests/api/v1/DummyTestApp/Resources/AskDnsIp.template b/functionaltests/api/v1/DummyTestApp/Resources/AskDnsIp.template new file mode 100644 index 00000000..6d6bd402 --- /dev/null +++ b/functionaltests/api/v1/DummyTestApp/Resources/AskDnsIp.template @@ -0,0 +1,12 @@ +{ + "Scripts": [ + "Get-DnsListeningIpAddress.ps1" + ], + "Commands": [ + { + "Name": "Get-DnsListeningIpAddress", + "Arguments": {} + } + ], + "RebootOnCompletion": 0 +} \ No newline at end of file diff --git a/functionaltests/api/v1/DummyTestApp/Resources/CreatePrimaryDC.template b/functionaltests/api/v1/DummyTestApp/Resources/CreatePrimaryDC.template new file mode 100644 index 00000000..6633057d --- /dev/null +++ b/functionaltests/api/v1/DummyTestApp/Resources/CreatePrimaryDC.template @@ -0,0 +1,16 @@ +{ + "Scripts": [ + "ImportCoreFunctions.ps1", + "Install-RolePrimaryDomainController.ps1" + ], + "Commands": [ + { + "Name": "Install-RolePrimaryDomainController", + "Arguments": { + "DomainName": "$domain", + "SafeModePassword": "$recoveryPassword" + } + } + ], + "RebootOnCompletion": 1 +} diff --git a/functionaltests/api/v1/DummyTestApp/Resources/CreateSecondaryDC.template b/functionaltests/api/v1/DummyTestApp/Resources/CreateSecondaryDC.template new file mode 100644 index 00000000..4512ee5a --- /dev/null +++ b/functionaltests/api/v1/DummyTestApp/Resources/CreateSecondaryDC.template @@ -0,0 +1,18 @@ +{ + "Scripts": [ + "ImportCoreFunctions.ps1", + "Install-RoleSecondaryDomainController.ps1" + ], + "Commands": [ + { + "Name": "Install-RoleSecondaryDomainController", + "Arguments": { + "DomainName": "$domain", + "UserName": "$domainAccountName", + "Password": "$domainPassword", + "SafeModePassword": "$recoveryPassword" + } + } + ], + "RebootOnCompletion": 1 +} \ No newline at end of file diff --git a/functionaltests/api/v1/DummyTestApp/Resources/JoinDomain.template b/functionaltests/api/v1/DummyTestApp/Resources/JoinDomain.template new file mode 100644 index 00000000..3d8cbeff --- /dev/null +++ b/functionaltests/api/v1/DummyTestApp/Resources/JoinDomain.template @@ -0,0 +1,25 @@ +{ + "Scripts": [ + "ImportCoreFunctions.ps1", + "Join-Domain.ps1" + ], + "Commands": [ + { + "Name": "Set-NetworkAdapterConfiguration", + "Arguments": { + "FirstAvailable": true, + "DNSServer": "$dnsIp" + } + }, + { + "Name": "Join-Domain", + "Arguments": { + "Username": "$domainUser", + "Password": "$domainPassword", + "DomainName": "$domain", + "OUPath": "$ouPath" + } + } + ], + "RebootOnCompletion": 1 +} \ No newline at end of file diff --git a/functionaltests/api/v1/DummyTestApp/Resources/SetPassword.template b/functionaltests/api/v1/DummyTestApp/Resources/SetPassword.template new file mode 100644 index 00000000..101db0ea --- /dev/null +++ b/functionaltests/api/v1/DummyTestApp/Resources/SetPassword.template @@ -0,0 +1,17 @@ +{ + "Scripts": [ + "ImportCoreFunctions.ps1", + "Set-LocalUserPassword.ps1" + ], + "Commands": [ + { + "Name": "Set-LocalUserPassword", + "Arguments": { + "UserName": "Administrator", + "Password": "$adminPassword", + "Force": true + } + } + ], + "RebootOnCompletion": 0 +} \ No newline at end of file diff --git a/functionaltests/api/v1/DummyTestApp/Resources/scripts/Get-DnsListeningIpAddress.ps1 b/functionaltests/api/v1/DummyTestApp/Resources/scripts/Get-DnsListeningIpAddress.ps1 new file mode 100644 index 00000000..1db0b85f --- /dev/null +++ b/functionaltests/api/v1/DummyTestApp/Resources/scripts/Get-DnsListeningIpAddress.ps1 @@ -0,0 +1,7 @@ + +function Get-DnsListeningIpAddress { + Import-Module DnsServer + + (Get-DNSServer -ComputerName localhost).ServerSetting.ListeningIpAddress | + Where-Object { $_ -match "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" } +} diff --git a/functionaltests/api/v1/DummyTestApp/Resources/scripts/ImportCoreFunctions.ps1 b/functionaltests/api/v1/DummyTestApp/Resources/scripts/ImportCoreFunctions.ps1 new file mode 100644 index 00000000..85e64349 --- /dev/null +++ b/functionaltests/api/v1/DummyTestApp/Resources/scripts/ImportCoreFunctions.ps1 @@ -0,0 +1,68 @@ + +Import-Module CoreFunctions -Force +Initialize-Logger 'MuranoAgent' 'C:\Murano\PowerShell.log' + + +function Show-InvocationInfo { + param ( + $Invocation, + [Switch] $End + ) + + if ($End) { + Write-LogDebug "" + } + else { + Write-LogDebug "" + Write-LogDebug "" + foreach ($Parameter in $Invocation.MyCommand.Parameters) { + foreach ($Key in $Parameter.Keys) { + $Type = $Parameter[$Key].ParameterType.FullName + foreach ($Value in $Invocation.BoundParameters[$Key]) { + Write-LogDebug "[$Type] $Key = '$Value'" + } + } + } + Write-LogDebug "" + } +} + + +$TrapHandler = { + Write-LogError "" + Write-LogError $_ -EntireObject + Write-LogError "" + break +} + + +trap { + &$TrapHandler +} + +$ErrorActionPreference = 'Stop' + + +<# +# Usage example for Show-InvocationInfo + +function MyFunction { + param ( + [String] $Value1, + [String] $Value2, + [Int] $Int1 + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + # Main code here + } +} +#> diff --git a/functionaltests/api/v1/DummyTestApp/Resources/scripts/Install-RolePrimaryDomainController.ps1 b/functionaltests/api/v1/DummyTestApp/Resources/scripts/Install-RolePrimaryDomainController.ps1 new file mode 100644 index 00000000..e8f1e5a9 --- /dev/null +++ b/functionaltests/api/v1/DummyTestApp/Resources/scripts/Install-RolePrimaryDomainController.ps1 @@ -0,0 +1,43 @@ + +trap { + &$TrapHandler +} + + +Function Install-RolePrimaryDomainController { + param ( + [String] $DomainName, + [String] $SafeModePassword + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + Add-WindowsFeatureWrapper ` + -Name "DNS","AD-Domain-Services","RSAT-DFS-Mgmt-Con" ` + -IncludeManagementTools ` + -NotifyRestart + + Write-Log "Creating first domain controller ..." + + $SMAP = ConvertTo-SecureString -String $SafeModePassword -AsPlainText -Force + + $null = Install-ADDSForest ` + -DomainName $DomainName ` + -SafeModeAdministratorPassword $SMAP ` + -DomainMode Default ` + -ForestMode Default ` + -NoRebootOnCompletion ` + -Force + + Write-Log "Waiting 60 seconds for reboot ..." + Start-Sleep -Seconds 60 + } +} diff --git a/functionaltests/api/v1/DummyTestApp/Resources/scripts/Install-RoleSecondaryDomainController.ps1 b/functionaltests/api/v1/DummyTestApp/Resources/scripts/Install-RoleSecondaryDomainController.ps1 new file mode 100644 index 00000000..be9258ed --- /dev/null +++ b/functionaltests/api/v1/DummyTestApp/Resources/scripts/Install-RoleSecondaryDomainController.ps1 @@ -0,0 +1,69 @@ + +trap { + &$TrapHandler +} + + +Function Install-RoleSecondaryDomainController +{ +<# +.SYNOPSIS +Install additional (secondary) domain controller. + +#> + param + ( + [String] + # Domain name to join to. + $DomainName, + + [String] + # Domain user who is allowed to join computer to domain. + $UserName, + + [String] + # User's password. + $Password, + + [String] + # Domain controller recovery mode password. + $SafeModePassword + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + $Credential = New-Credential -UserName "$DomainName\$UserName" -Password $Password + + # Add required windows features + Add-WindowsFeatureWrapper ` + -Name "DNS","AD-Domain-Services","RSAT-DFS-Mgmt-Con" ` + -IncludeManagementTools ` + -NotifyRestart + + + Write-Log "Adding secondary domain controller ..." + + $SMAP = ConvertTo-SecureString -String $SafeModePassword -AsPlainText -Force + + Install-ADDSDomainController ` + -DomainName $DomainName ` + -SafeModeAdministratorPassword $SMAP ` + -Credential $Credential ` + -NoRebootOnCompletion ` + -Force ` + -ErrorAction Stop | Out-Null + + Write-Log "Waiting for restart ..." + # Stop-Execution -ExitCode 3010 -ExitString "Computer must be restarted to finish domain controller promotion." + # Write-Log "Restarting computer ..." + # Restart-Computer -Force + } +} diff --git a/functionaltests/api/v1/DummyTestApp/Resources/scripts/Join-Domain.ps1 b/functionaltests/api/v1/DummyTestApp/Resources/scripts/Join-Domain.ps1 new file mode 100644 index 00000000..403ef798 --- /dev/null +++ b/functionaltests/api/v1/DummyTestApp/Resources/scripts/Join-Domain.ps1 @@ -0,0 +1,67 @@ + +trap { + &$TrapHandler +} + + +Function Join-Domain { +<# +.SYNOPSIS +Executes "Join domain" action. + +Requires 'CoreFunctions' module +#> + param ( + [String] $DomainName = '', + [String] $UserName = '', + [String] $Password = '', + [String] $OUPath = '', + [Switch] $AllowRestart + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + if ($UserName -eq '') { + $UserName = 'Administrator' + } + + $Credential = New-Credential -UserName "$DomainName\$UserName" -Password $Password + + + if (Test-ComputerName -DomainName $DomainName -ErrorAction 'SilentlyContinue') { + Write-LogWarning "Computer already joined to domain '$DomainName'" + } + else { + Write-Log "Joining computer to domain '$DomainName' ..." + + if ($OUPath -eq '') { + Add-Computer -DomainName $DomainName -Credential $Credential -Force + } + else { + Add-Computer -DomainName $DomainName -Credential $Credential -OUPath $OUPath -Force + } + + $null = Exec 'ipconfig' @('/registerdns') -RedirectStreams + + Write-Log "Waiting 30 seconds to restart ..." + Start-Sleep -Seconds 30 + <# + if ($AllowRestart) { + Write-Log "Restarting computer ..." + Restart-Computer -Force + } + else { + Write-Log "Please restart the computer now." + } + #> + } + } +} diff --git a/functionaltests/api/v1/DummyTestApp/Resources/scripts/Set-LocalUserPassword.ps1 b/functionaltests/api/v1/DummyTestApp/Resources/scripts/Set-LocalUserPassword.ps1 new file mode 100644 index 00000000..8708a0f4 --- /dev/null +++ b/functionaltests/api/v1/DummyTestApp/Resources/scripts/Set-LocalUserPassword.ps1 @@ -0,0 +1,37 @@ + +trap { + &$TrapHandler +} + + +Function Set-LocalUserPassword { + param ( + [String] $UserName, + [String] $Password, + [Switch] $Force + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + if ((Get-WmiObject Win32_UserAccount -Filter "LocalAccount = 'True' AND Name='$UserName'") -eq $null) { + throw "Unable to find local user account '$UserName'" + } + + if ($Force) { + Write-Log "Changing password for user '$UserName' to '*****'" # :) + $null = ([ADSI] "WinNT://./$UserName").SetPassword($Password) + } + else { + Write-LogWarning "You are trying to change password for user '$UserName'. To do this please run the command again with -Force parameter." + } + } +} + diff --git a/functionaltests/api/v1/DummyTestApp/UI/ui.yaml b/functionaltests/api/v1/DummyTestApp/UI/ui.yaml new file mode 100644 index 00000000..9fab3d41 --- /dev/null +++ b/functionaltests/api/v1/DummyTestApp/UI/ui.yaml @@ -0,0 +1,165 @@ +Version: 2 + +Templates: + primaryController: + ?: + type: io.murano.windows.Dummy.PrimaryController + host: + ?: + type: io.murano.services.windows.Host + adminPassword: $.serviceConfiguration.adminPassword + name: generateHostname($.serviceConfiguration.unitNamingPattern, 1) + flavor: $.instanceConfiguration.flavor + image: $.instanceConfiguration.osImage + + secondaryController: + ?: + type: io.murano.windows.Dummy.SecondaryController + host: + ?: + type: io.murano.services.windows.Host + adminPassword: $.serviceConfiguration.adminPassword + name: generateHostname($.serviceConfiguration.unitNamingPattern, $index + 1) + flavor: $.instanceConfiguration.flavor + image: $.instanceConfiguration.osImage + +Application: + ?: + type: io.murano.windows.Dummy.Dummy + name: $.serviceConfiguration.name + primaryController: $primaryController + secondaryControllers: repeat($secondaryController, $.serviceConfiguration.dcInstances - 1) + +Forms: + - serviceConfiguration: + fields: + - name: configuration + type: string + hidden: true + initial: standalone + - name: name + type: string + label: Domain Name + description: >- + Enter a desired name for a new domain. This name should fit to + DNS Domain Name requirements: it should contain + only A-Z, a-z, 0-9, (.) and (-) and should not end with a dash. + DNS server will be automatically set up on each of the Domain + Controller instances. Note: Only first 15 characters or characters + before first period is used as NetBIOS name. + minLength: 2 + maxLength: 255 + validators: + - expr: + regexpValidator: '^([0-9A-Za-z]|[0-9A-Za-z][0-9A-Za-z-]*[0-9A-Za-z])\.[0-9A-Za-z][0-9A-Za-z-]*[0-9A-Za-z]$' + message: >- + Only letters, numbers and dashes in the middle are + allowed. Period characters are allowed only when they + are used to delimit the components of domain style + names. Single-level domain is not + appropriate. Subdomains are not allowed. + - expr: + regexpValidator: '(^[^.]+$|^[^.]{1,15}\..*$)' + message: >- + NetBIOS name cannot be shorter than 1 symbol and + longer than 15 symbols. + - expr: + regexpValidator: '(^[^.]+$|^[^.]*\.[^.]{2,63}.*$)' + message: >- + DNS host name cannot be shorter than 2 symbols and + longer than 63 symbols. + helpText: >- + Just letters, numbers and dashes are allowed. + A dot can be used to create subdomains + - name: dcInstances + type: integer + label: Instance Count + description: >- + You can create several Active Directory instances by setting + instance number larger than one. One primary Domain Controller + and a few secondary DCs will be created. + minValue: 1 + maxValue: 100 + initial: 1 + helpText: Enter an integer value between 1 and 100 + - name: adminAccountName + type: string + label: Account Name + initial: Administrator + regexpValidator: '^[-\w]+$' + errorMessages: + invalid: 'Just letters, numbers, underscores and hyphens are allowed.' + - name: adminPassword + type: password + label: Administrator password + descriptionTitle: Passwords + description: >- + Windows requires strong password for service administration. + Your password should have at least one letter in each + register, a number and a special character. Password length should be + a minimum of 7 characters. + + Once you forget your password you won't be able to + operate the service until recovery password would be entered. So it's + better for Recovery and Administrator password to be different. + - name: recoveryPassword + type: password + label: Recovery password + - name: assignFloatingIP + required: false + type: floatingip + label: Assign Floating IP + description: >- + Select to true to assign floating IP automatically to Primary DC + initial: false + required: false + widgetMedia: + css: {all: ['muranodashboard/css/checkbox.css']} + - name: unitNamingPattern + type: string + label: Hostname template + description: >- + For your convenience all instance hostnames can be named + in the same way. Enter a name and use # character for incrementation. + For example, host# turns into host1, host2, etc. Please follow Windows + hostname restrictions. + required: false + regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$' + # FIXME: does not work for # turning into 2-digit numbers + maxLength: 15 + helpText: Optional field for a machine hostname template + # temporaryHack + widgetMedia: + js: ['muranodashboard/js/support_placeholder.js'] + css: {all: ['muranodashboard/css/support_placeholder.css']} + validators: + # if unitNamingPattern is given and dcInstances > 1, then '#' should occur in unitNamingPattern + - expr: $.serviceConfiguration.dcInstances < 2 or not $.serviceConfiguration.unitNamingPattern.bool() or '#' in $.serviceConfiguration.unitNamingPattern + message: Incrementation symbol "#" is required in the Hostname template + - instanceConfiguration: + fields: + - name: title + type: string + required: false + hidden: true + descriptionTitle: Instance Configuration + description: Specify some instance parameters on which service would be created. + - name: flavor + type: flavor + label: Instance flavor + description: >- + Select registered in Openstack flavor. Consider that service performance + depends on this parameter. + required: false + - name: osImage + type: image + imageType: windows + label: Instance image + description: >- + Select valid image for a service. Image should already be prepared and + registered in glance. + - name: availabilityZone + type: azone + label: Availability zone + description: Select availability zone where service would be installed. + required: false diff --git a/functionaltests/api/v1/DummyTestApp/logo2.png b/functionaltests/api/v1/DummyTestApp/logo2.png new file mode 100644 index 0000000000000000000000000000000000000000..e1a24717ead46edf8a7a111f11a97e48bde97693 GIT binary patch literal 11634 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 Cd~?zO literal 0 HcmV?d00001 diff --git a/functionaltests/api/v1/DummyTestApp/manifest.yaml b/functionaltests/api/v1/DummyTestApp/manifest.yaml new file mode 100644 index 00000000..ae7c6801 --- /dev/null +++ b/functionaltests/api/v1/DummyTestApp/manifest.yaml @@ -0,0 +1,26 @@ +Format: 1.0 + +Type: Application + +FullName: io.murano.windows.Dummy + +Name: Dummy + +Description: | + Dummy + +Author: 'murano.io' + +Tags: [Dummy] + +Classes: + io.murano.windows.Host: Host.yaml + io.murano.windows.DomainHost: DomainHost.yaml + io.murano.windows.Dummy.Dummy: Dummy.yaml + io.murano.windows.Dummy.Controller: Controller.yaml + io.murano.windows.Dummy.PrimaryController: PrimaryController.yaml + io.murano.windows.Dummy.SecondaryController: SecondaryController.yaml + +# UI: ui.yaml # default to ui.yaml, will use default if skipped + +Logo: logo2.png # defaults to logo.png, will use default if skipped diff --git a/functionaltests/api/v1/test_repository.py b/functionaltests/api/v1/test_repository.py index 6e12ac30..2e075513 100644 --- a/functionaltests/api/v1/test_repository.py +++ b/functionaltests/api/v1/test_repository.py @@ -12,19 +12,63 @@ # License for the specific language governing permissions and limitations # under the License. +import os +import zipfile + from tempest.test import attr +#from tempest import exceptions +#Need uncomment after fix https://bugs.launchpad.net/murano/+bug/1309413 +#it will be use in tearDown method + from functionaltests.api import base -class TestRepository(base.TestCase): +class TestCaseRepository(base.TestCase): @classmethod def setUpClass(cls): - super(TestRepository, cls).setUpClass() + super(TestCaseRepository, cls).setUpClass() - raise cls.skipException("Murano Repository tests are disabled") + cls.location = os.path.realpath( + os.path.join(os.getcwd(), os.path.dirname(__file__))) + + __folderpath__ = os.path.join(cls.location, "DummyTestApp") + __rootlen__ = len(__folderpath__) + 1 + + with zipfile.ZipFile(os.path.join(cls.location, + "DummyTestApp.zip"), "w") as zf: + for dirname, _, files in os.walk(__folderpath__): + for filename in files: + fn = os.path.join(dirname, filename) + zf.write(fn, fn[__rootlen__:]) + + def setUp(self): + super(TestCaseRepository, self).setUp() + + self.packages = [] + + def tearDown(self): + super(TestCaseRepository, self).tearDown() + + for package in self.packages: + try: + self.client.delete_package(package['id']) + except Exception: + #except exceptions.NotFound: Need to uncomment after fix the + #following bug https://bugs.launchpad.net/murano/+bug/1309413 + pass + + @classmethod + def tearDownClass(cls): + + super(TestCaseRepository, cls).tearDownClass() + + os.remove(os.path.join(cls.location, "DummyTestApp.zip")) + + +class TestRepositorySanity(TestCaseRepository): @attr(type='smoke') def test_get_list_packages(self): @@ -33,65 +77,176 @@ class TestRepository(base.TestCase): self.assertEqual(200, resp.status) self.assertTrue(isinstance(body['packages'], list)) - @attr(type='smoke') - def test_get_package(self): - _, body = self.client.get_list_packages() - package = body['packages'][0] - - resp, body = self.client.get_package(package['id']) - - self.assertEqual(200, resp.status) - self.assertEqual(package, body) - - @attr(type='smoke') - def test_update_package(self): - _, body = self.client.get_list_packages() - package = body['packages'][0] - - resp, body = self.client.update_package(package['id']) - - self.assertEqual(200, resp.status) - self.assertIn("i'm a test", body['tags']) - - @attr(type='smoke') - def test_delete_package(self): - _, body = self.client.get_list_packages() - package = body['packages'][0] - - resp, _ = self.client.delete_package(package['id']) - - self.assertEqual(200, resp.status) - - @attr(type='smoke') - def test_download_package(self): - _, body = self.client.get_list_packages() - package = body['packages'][0] - - resp, _ = self.client.download_package(package['id']) - - self.assertEqual(200, resp.status) - - @attr(type='smoke') - def test_get_ui_definitions(self): - _, body = self.client.get_list_packages() - package = body['packages'][0] - - resp, _ = self.client.get_ui_definition(package['id']) - - self.assertEqual(200, resp.status) - - @attr(type='smoke') - def test_get_logo(self): - _, body = self.client.get_list_packages() - package = body['packages'][0] - - resp, _ = self.client.get_logo(package['id']) - - self.assertEqual(200, resp.status) - @attr(type='smoke') def test_get_list_categories(self): resp, body = self.client.list_categories() self.assertEqual(200, resp.status) self.assertTrue(isinstance(body['categories'], list)) + + @attr(type='smoke') + def test_upload_and_delete_package(self): + packages_list = self.client.get_list_packages()[1] + for package in packages_list['packages']: + if 'Dummy' in package['fully_qualified_name']: + self.client.delete_package(package['id']) + categorie = self.client.list_categories()[1]['categories'][0] + packages_list = self.client.get_list_packages()[1]['packages'] + + resp = self.client.upload_package( + 'testpackage', + {"categories": [categorie], "tags": ["windows"]}) + self.packages.append(resp.json()) + + _packages_list = self.client.get_list_packages()[1]['packages'] + + self.assertEqual(200, resp.status_code) + self.assertEqual(len(packages_list) + 1, len(_packages_list)) + + resp = self.client.delete_package(resp.json()['id'])[0] + + _packages_list = self.client.get_list_packages()[1]['packages'] + + self.assertEqual(200, resp.status) + self.assertEqual(len(packages_list), len(_packages_list)) + + +class TestRepository(TestCaseRepository): + + @classmethod + def setUpClass(cls): + + super(TestRepository, cls).setUpClass() + cls.categorie = cls.client.list_categories()[1]['categories'][0] + + def setUp(self): + super(TestRepository, self).setUp() + + packages_list = self.client.get_list_packages()[1] + for package in packages_list['packages']: + if 'Dummy' in package['fully_qualified_name']: + self.client.delete_package(package['id']) + self.package = self.client.upload_package( + 'testpackage', + {"categories": [self.categorie], "tags": ["windows"]}).json() + self.packages.append(self.package) + + @attr(type='smoke') + def test_get_package(self): + resp, body = self.client.get_package(self.package['id']) + + self.assertEqual(200, resp.status) + self.assertEqual(self.package['tags'], body['tags']) + + @attr(type='smoke') + def test_update_package(self): + post_body = [ + { + "op": "add", + "path": "/tags", + "value": ["im a test"] + } + ] + + resp, body = self.client.update_package(self.package['id'], post_body) + + self.assertEqual(200, resp.status) + self.assertIn("im a test", body['tags']) + + post_body = [ + { + "op": "replace", + "path": "/tags", + "value": ["im bad:D"] + } + ] + + resp, body = self.client.update_package(self.package['id'], post_body) + + self.assertEqual(200, resp.status) + self.assertNotIn("im a test", body['tags']) + self.assertIn("im bad:D", body['tags']) + + post_body = [ + { + "op": "remove", + "path": "/tags", + "value": ["im bad:D"] + } + ] + + resp, body = self.client.update_package(self.package['id'], post_body) + + self.assertEqual(200, resp.status) + self.assertNotIn("im bad:D", body['tags']) + + post_body = [ + { + "op": "replace", + "path": "/is_public", + "value": True + } + ] + + resp, body = self.client.update_package(self.package['id'], post_body) + + self.assertEqual(200, resp.status) + self.assertTrue(body['is_public']) + + post_body = [ + { + "op": "replace", + "path": "/enabled", + "value": True + } + ] + + resp, body = self.client.update_package(self.package['id'], post_body) + + self.assertEqual(200, resp.status) + self.assertTrue(body['enabled']) + + post_body = [ + { + "op": "replace", + "path": "/description", + "value": "New description" + } + ] + + resp, body = self.client.update_package(self.package['id'], post_body) + + self.assertEqual(200, resp.status) + self.assertEqual("New description", body['description']) + + post_body = [ + { + "op": "replace", + "path": "/name", + "value": "New name" + } + ] + + resp, body = self.client.update_package(self.package['id'], post_body) + + self.assertEqual(200, resp.status) + self.assertEqual("New name", body['name']) + + @attr(type='smoke') + def test_download_package(self): + resp = self.client.download_package(self.package['id'])[0] + + self.assertEqual(200, resp.status) + + @attr(type='smoke') + def test_get_ui_definitions(self): + resp = self.client.get_ui_definition(self.package['id'])[0] + + self.assertEqual(200, resp.status) + + @attr(type='smoke') + def test_get_logo(self): + resp, body = self.client.get_logo(self.package['id']) + + self.assertEqual(200, resp.status) + self.assertTrue(isinstance(body, str)) diff --git a/functionaltests/run_tests.sh b/functionaltests/run_tests.sh index a8dc82f5..b8d4af7c 100755 --- a/functionaltests/run_tests.sh +++ b/functionaltests/run_tests.sh @@ -28,4 +28,4 @@ TEMPEST_DIR=${TEMPEST_DIR:-/opt/stack/new/tempest} # Add tempest source tree to PYTHONPATH export PYTHONPATH=$PYTHONPATH:$TEMPEST_DIR -nosetests -v . +nosetests -sv .