Merge remote-tracking branch 'upstream/master' into batchDelection

This commit is contained in:
pfh 2018-01-29 16:41:47 +08:00
commit dca8459a13
29 changed files with 317 additions and 49 deletions

View File

@ -284,9 +284,11 @@ modify_composefile: modify_composefile_notary modify_composefile_clair
@cp $(DOCKERCOMPOSEFILEPATH)/$(DOCKERCOMPOSETPLFILENAME) $(DOCKERCOMPOSEFILEPATH)/$(DOCKERCOMPOSEFILENAME) @cp $(DOCKERCOMPOSEFILEPATH)/$(DOCKERCOMPOSETPLFILENAME) $(DOCKERCOMPOSEFILEPATH)/$(DOCKERCOMPOSEFILENAME)
@cp $(DOCKERCOMPOSEFILEPATH)/ha/$(DOCKERCOMPOSETPLFILENAME) $(DOCKERCOMPOSEFILEPATH)/ha/$(DOCKERCOMPOSEFILENAME) @cp $(DOCKERCOMPOSEFILEPATH)/ha/$(DOCKERCOMPOSETPLFILENAME) $(DOCKERCOMPOSEFILEPATH)/ha/$(DOCKERCOMPOSEFILENAME)
@$(SEDCMD) -i 's/__version__/$(VERSIONTAG)/g' $(DOCKERCOMPOSEFILEPATH)/ha/$(DOCKERCOMPOSEFILENAME) @$(SEDCMD) -i 's/__version__/$(VERSIONTAG)/g' $(DOCKERCOMPOSEFILEPATH)/ha/$(DOCKERCOMPOSEFILENAME)
@$(SEDCMD) -i 's/__reg_version__/$(REGISTRYVERSION)-$(VERSIONTAG)/g' $(DOCKERCOMPOSEFILEPATH)/$(DOCKERCOMPOSEFILENAME)
@$(SEDCMD) -i 's/__version__/$(VERSIONTAG)/g' $(DOCKERCOMPOSEFILEPATH)/$(DOCKERCOMPOSEFILENAME) @$(SEDCMD) -i 's/__version__/$(VERSIONTAG)/g' $(DOCKERCOMPOSEFILEPATH)/$(DOCKERCOMPOSEFILENAME)
@$(SEDCMD) -i 's/__reg_version__/$(REGISTRYVERSION)-$(VERSIONTAG)/g' $(DOCKERCOMPOSEFILEPATH)/$(DOCKERCOMPOSEFILENAME)
@$(SEDCMD) -i 's/__reg_version__/$(REGISTRYVERSION)-$(VERSIONTAG)/g' $(DOCKERCOMPOSEFILEPATH)/ha/$(DOCKERCOMPOSEFILENAME)
@$(SEDCMD) -i 's/__nginx_version__/$(NGINXVERSION)/g' $(DOCKERCOMPOSEFILEPATH)/$(DOCKERCOMPOSEFILENAME) @$(SEDCMD) -i 's/__nginx_version__/$(NGINXVERSION)/g' $(DOCKERCOMPOSEFILEPATH)/$(DOCKERCOMPOSEFILENAME)
@$(SEDCMD) -i 's/__nginx_version__/$(NGINXVERSION)/g' $(DOCKERCOMPOSEFILEPATH)/ha/$(DOCKERCOMPOSEFILENAME)
modify_composefile_notary: modify_composefile_notary:
@echo "preparing docker-compose notary file..." @echo "preparing docker-compose notary file..."

104
docs/expand_hard_disk.md Normal file
View File

@ -0,0 +1,104 @@
# Expand the Hard Disk of Virtual Appliance
If you install Harbor with OVA, the persistent data(such as images and database) is stored in a hard disk which is mounted on directory "/data", and the default size is 60GB. As more and more images are pushed into it, the capacity may not meet your requirements.
You can check the space on Harbor web UI by clicking on **Projects**:
![lvm](img/lvm/check_on_ui_01.png)
If your free space is running out, you can expand the size of the hard disk by the following steps:
1. Add New Hard Disk to VM
(1) Log in vSphere web client. Power off Harbor's virtual appliance.
(2) Right click on the VM and select "Edit Settings".
(3) Select "New Hard Disk", and click "OK".
![lvm](img/lvm/add_new_hard_disk.png)
We add a 10GB new hard disk to show the operations.
(4) Power on the VM.
2. Expand Hard Disk using LVM
Login from the console of the virtual appliance and run the following commands:
(1) Check the current size of "/data":
```sh
df -h /data
```
![lvm](img/lvm/size_of_data_01.png)
(2) Find the new hard disk, e.g. "/dev/sdc". Replace all "/dev/sdc" with your disk in the following commands.
```sh
fdisk -l
```
![lvm](img/lvm/find_the_new_harddisk.png)
(3) Create new physical volume:
```sh
pvcreate /dev/sdc
```
(4) Check the volume group:
```sh
vgdisplay
```
![lvm](img/lvm/vg_01.png)
(5) Expand the volume group:
```sh
vgextend data1_vg /dev/sdc
```
(6) Check the volume group again:
```sh
vgdisplay
```
![lvm](img/lvm/vg_02.png)
(7) Check the logical volume:
```sh
lvdisplay
```
![lvm](img/lvm/lv_01.png)
(8) Resize the logical volume:
```sh
lvresize -l +100%FREE /dev/data1_vg/data
```
![lvm](img/lvm/resize_lv.png)
(9) Check the logical volume again, note the change of "LV Size":
```sh
lvdisplay
```
![lvm](img/lvm/lv_02.png)
(10) Resize the file system:
```sh
resize2fs /dev/data1_vg/data
```
(11) Check the size "/data" again:
```sh
df -h /data
```
![lvm](img/lvm/size_of_data_02.png)
You can also check the size on Harbor web UI:
![lvm](img/lvm/check_on_ui.png)
After that, your disk should be expanded successfully. If you want to add more hard disks, do the steps again.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

View File

@ -110,4 +110,8 @@
![Screenshot of after login](img/ovainstall/afterlogin.png) ![Screenshot of after login](img/ovainstall/afterlogin.png)
Please run "tdnf distro-sync" command from time to time to keep the OS up to date. To migrate Harbor OVA, please refer [migrate OVA guide](migrate_ova_guide.md)
To extend the data disk in Harbor OVA, please refer [Expand the Hard Disk of Virtual Appliance](expand_hard_disk.md)
Please run "tdnf distro-sync" command from time to time to keep the OS up to date.

41
docs/migrate_ova_guide.md Normal file
View File

@ -0,0 +1,41 @@
# Harbor OVA upgrade and database migration guide
This guide is limited to migrate a Harbor OVA instance to a next release. All Harbor data storeage settings is not manually changed after the existing Harbor OVA deployed.
**Steps to migrate Harbor OVA instances:**
1. Before migration, you need to note down these following items:
- Note down the value of db_password in /data/harbor.cfg.
- **"Networking properties"** if need to keep these settings. you can find them in **"Edit Settings"** -> **"vApp Options"**
![Screenshot of vApp Options](img/ovainstall/vappoptions.png)
2. In the vSphere Web Client, Select **"Shut Down Guest OS"** on the existing OVA instances, then select **"Edit Settings"**, remove the **"Hard disk 2"**, uncheck **"Delete files from datastore"**. All disks in the logical volume "data1_vg" should be removed if the original logic volume have been extended. Use pvscan command to check disks in logical volume "data1_vg".
![Screenshot of pvscan](img/ovainstall/pvscan.png)
Usually, the sda is the Hard Disk1 in the **"Edit Settings"** pannel, and the sdb is Hard Disk2 and so on. Note down all location of disk files in logical volume "data1_vg".
![Screenshot of Remove Disk](img/ovainstall/removedisk.png)
3. Deploy a new Harbor OVA instances. You may use different settings or keep same settings.
| Configuration Section Name |Use Different Settings | Keep Same Settings |
|-------------------------------- | ------------------|--------------------------------------------- |
| Certificates | Leave blank to use auto-generated certificates or paste in new certificates |Replace files in /data/ca_download and /data/cert with backup files in the same path of prevous Harbor instance and restart Harbor OVA after migration |
| Harbor Configuration | N/A |Input a random administrator password to bypass the data validation, it uses previous settings after migration |
| LDAP Configuration | N/A |Leave blank, it uses previous settings after migration |
| Networking Properties | Input new settings | Input previous settings |
| System | Input new settings | Input previous settings |
4. Copy all disk files of logic volume "data1_vg" in Step 2 to the new Harbor OVA's folder in vSphere's datastore.
5. Before powering on the new Harbor OVA instances, select **"Edit Settings"**, after remove the "Hard disk 2", then click **" Existing Hard Disk"** in **"New Device"**, let it point to the disk file copied in Step 4. Please add all disk files in the same order with previous OVA instance.
6. Power on the new OVA instance, login to the console and run following commands:
```
chmod 700 /migrate_OVA.sh
/migrate_OVA.sh
```
When prompt, input the value of db_password that note down in Step 1.
7. After the script is complete, visit URL: https://*<DNS Name>* to verify the new Harbor OVA instance. the administrator's password is the same password of previous Harbor instance.

View File

@ -9,6 +9,8 @@ When upgrading your existing Habor instance to a newer version, you may need to
- You must back up your data before any data migration. - You must back up your data before any data migration.
- To migrate harbor OVA, please refer [migrate OVA guide](migrate_ova_guide.md)
### Upgrading Harbor and migrating data ### Upgrading Harbor and migrating data
1. Log in to the host that Harbor runs on, stop and remove existing Harbor instance if it is still running: 1. Log in to the host that Harbor runs on, stop and remove existing Harbor instance if it is still running:

View File

@ -2,7 +2,7 @@ swagger: '2.0'
info: info:
title: Harbor API title: Harbor API
description: These APIs provide services for manipulating Harbor project. description: These APIs provide services for manipulating Harbor project.
version: 0.3.0 version: 1.4.0
host: localhost host: localhost
schemes: schemes:
- http - http
@ -11,7 +11,6 @@ produces:
- application/json - application/json
- text/plain - text/plain
consumes: consumes:
- text/plain
- application/json - application/json
paths: paths:
/search: /search:
@ -142,6 +141,8 @@ paths:
description: User need to log in first. description: User need to log in first.
'409': '409':
description: Project name already exists. description: Project name already exists.
'415':
$ref: '#/responses/UnsupportedMediaType'
'500': '500':
description: Unexpected internal errors. description: Unexpected internal errors.
'/projects/{project_id}': '/projects/{project_id}':
@ -355,6 +356,8 @@ paths:
description: User does not have permission to the project. description: User does not have permission to the project.
'404': '404':
description: Project ID does not exist. description: Project ID does not exist.
'415':
$ref: '#/responses/UnsupportedMediaType'
'500': '500':
description: Internal server errors. description: Internal server errors.
'/projects/{project_id}/metadatas/{meta_name}': '/projects/{project_id}/metadatas/{meta_name}':
@ -511,6 +514,8 @@ paths:
description: Project ID or username does not exist. description: Project ID or username does not exist.
'409': '409':
description: User has already added as a project role member. description: User has already added as a project role member.
'415':
$ref: '#/responses/UnsupportedMediaType'
'500': '500':
description: Unexpected internal errors. description: Unexpected internal errors.
'/projects/{project_id}/members/{user_id}': '/projects/{project_id}/members/{user_id}':
@ -712,6 +717,8 @@ paths:
description: >- description: >-
User registration can only be used by admin role user when User registration can only be used by admin role user when
self-registration is off. self-registration is off.
'415':
$ref: '#/responses/UnsupportedMediaType'
'500': '500':
description: Unexpected internal errors. description: Unexpected internal errors.
/users/current: /users/current:
@ -1131,6 +1138,8 @@ paths:
description: User doesn't have permission to perform the action. description: User doesn't have permission to perform the action.
'404': '404':
description: The image does not exist in Harbor. description: The image does not exist in Harbor.
'415':
$ref: '#/responses/UnsupportedMediaType'
'503': '503':
description: Harbor is not deployed with Clair. description: Harbor is not deployed with Clair.
/repositories/scanAll: /repositories/scanAll:
@ -1146,7 +1155,9 @@ paths:
- name: project_id - name: project_id
in: query in: query
type: integer type: integer
description: When this parm is set only the images under the project identified by the project_id will be scanned. description: >-
When this parm is set only the images under the project identified
by the project_id will be scanned.
responses: responses:
'202': '202':
description: >- description: >-
@ -1156,6 +1167,8 @@ paths:
description: User needs to login or call the API with correct credentials. description: User needs to login or call the API with correct credentials.
'403': '403':
description: User doesn't have permission to perform the action. description: User doesn't have permission to perform the action.
'415':
$ref: '#/responses/UnsupportedMediaType'
'500': '500':
description: Failed to initiate the action. description: Failed to initiate the action.
'503': '503':
@ -1393,7 +1406,7 @@ paths:
description: Unexpected internal errors. description: Unexpected internal errors.
put: put:
summary: Update status of jobs. Only stop is supported for now. summary: Update status of jobs. Only stop is supported for now.
description: > description: |
The endpoint is used to stop the replication jobs of a policy. The endpoint is used to stop the replication jobs of a policy.
tags: tags:
- Products - Products
@ -1417,7 +1430,7 @@ paths:
description: Resource requested does not exist. description: Resource requested does not exist.
'500': '500':
description: Unexpected internal errors. description: Unexpected internal errors.
/jobs/replication/{id}: '/jobs/replication/{id}':
delete: delete:
summary: Delete specific ID job. summary: Delete specific ID job.
description: | description: |
@ -1442,7 +1455,7 @@ paths:
description: Project ID does not exist. description: Project ID does not exist.
'500': '500':
description: Unexpected internal errors. description: Unexpected internal errors.
/jobs/replication/{id}/log: '/jobs/replication/{id}/log':
get: get:
summary: Get job logs. summary: Get job logs.
description: | description: |
@ -1467,7 +1480,7 @@ paths:
description: The specific repository ID's log does not exist. description: The specific repository ID's log does not exist.
'500': '500':
description: Unexpected internal errors. description: Unexpected internal errors.
/jobs/scan/{id}/log: '/jobs/scan/{id}/log':
get: get:
summary: Get job logs. summary: Get job logs.
description: | description: |
@ -1492,7 +1505,6 @@ paths:
description: The specific repository ID's log does not exist. description: The specific repository ID's log does not exist.
'500': '500':
description: Unexpected internal errors. description: Unexpected internal errors.
/policies/replication: /policies/replication:
get: get:
summary: List filters policies by name and project_id summary: List filters policies by name and project_id
@ -1516,13 +1528,13 @@ paths:
type: integer type: integer
format: int32 format: int32
required: false required: false
description: 'The page nubmer.' description: The page nubmer.
- name: page_size - name: page_size
in: query in: query
type: integer type: integer
format: int32 format: int32
required: false required: false
description: 'The size of per page.' description: The size of per page.
tags: tags:
- Products - Products
responses: responses:
@ -1563,9 +1575,11 @@ paths:
description: >- description: >-
Policy name already used or policy already exists with the same Policy name already used or policy already exists with the same
project and target. project and target.
'415':
$ref: '#/responses/UnsupportedMediaType'
'500': '500':
description: Unexpected internal errors. description: Unexpected internal errors.
/policies/replication/{id}: '/policies/replication/{id}':
get: get:
summary: Get replication policy. summary: Get replication policy.
description: | description: |
@ -1604,7 +1618,7 @@ paths:
description: policy ID description: policy ID
- name: policyupdate - name: policyupdate
in: body in: body
description: 'Updated properties of the replication policy.' description: Updated properties of the replication policy.
required: true required: true
schema: schema:
$ref: '#/definitions/RepPolicy' $ref: '#/definitions/RepPolicy'
@ -1646,6 +1660,8 @@ paths:
description: User need to log in first. description: User need to log in first.
'404': '404':
description: The policy does not exist. description: The policy does not exist.
'415':
$ref: '#/responses/UnsupportedMediaType'
'500': '500':
description: Unexpected internal errors. description: Unexpected internal errors.
/targets: /targets:
@ -1695,6 +1711,8 @@ paths:
description: User need to log in first. description: User need to log in first.
'409': '409':
description: Replication target name already exists. description: Replication target name already exists.
'415':
$ref: '#/responses/UnsupportedMediaType'
'500': '500':
description: Unexpected internal errors. description: Unexpected internal errors.
/targets/ping: /targets/ping:
@ -1725,6 +1743,8 @@ paths:
target. target.
'404': '404':
description: Target not found. description: Target not found.
'415':
$ref: '#/responses/UnsupportedMediaType'
'500': '500':
description: Unexpected internal errors. description: Unexpected internal errors.
'/targets/{id}': '/targets/{id}':
@ -1852,6 +1872,8 @@ paths:
description: User need to log in first. description: User need to log in first.
'403': '403':
description: User does not have permission of admin role. description: User does not have permission of admin role.
'415':
$ref: '#/responses/UnsupportedMediaType'
'500': '500':
description: Unexpected internal errors. description: Unexpected internal errors.
/systeminfo: /systeminfo:
@ -1938,6 +1960,8 @@ paths:
description: User need to login first. description: User need to login first.
'403': '403':
description: Only admin has this authority. description: Only admin has this authority.
'415':
$ref: '#/responses/UnsupportedMediaType'
'500': '500':
description: Unexpected internal errors. description: Unexpected internal errors.
/ldap/users/search: /ldap/users/search:
@ -1977,6 +2001,8 @@ paths:
description: User need to login first. description: User need to login first.
'403': '403':
description: Only admin has this authority. description: Only admin has this authority.
'415':
$ref: '#/responses/UnsupportedMediaType'
'500': '500':
description: Unexpected internal errors. description: Unexpected internal errors.
/ldap/users/import: /ldap/users/import:
@ -2008,6 +2034,8 @@ paths:
description: User need to login first. description: User need to login first.
'403': '403':
description: Only admin has this authority. description: Only admin has this authority.
'415':
$ref: '#/responses/UnsupportedMediaType'
'500': '500':
description: Failed import some users. description: Failed import some users.
schema: schema:
@ -2046,7 +2074,9 @@ paths:
required: true required: true
schema: schema:
$ref: '#/definitions/Configurations' $ref: '#/definitions/Configurations'
description: The configuration map can contain a subset of the attributes of the schema, which are to be updated. description: >-
The configuration map can contain a subset of the attributes of the
schema, which are to be updated.
responses: responses:
'200': '200':
description: Modify system configurations successfully. description: Modify system configurations successfully.
@ -2071,6 +2101,8 @@ paths:
description: User need to log in first. description: User need to log in first.
'403': '403':
description: User does not have permission of admin role. description: User does not have permission of admin role.
'415':
$ref: '#/responses/UnsupportedMediaType'
'500': '500':
description: Unexpected internal errors. description: Unexpected internal errors.
/email/ping: /email/ping:
@ -2098,8 +2130,14 @@ paths:
description: User need to login first. description: User need to login first.
'403': '403':
description: Only admin has this authority. description: Only admin has this authority.
'415':
$ref: '#responses/UnsupportedMediaType'
'500': '500':
description: Unexpected internal errors. description: Unexpected internal errors.
responses:
UnsupportedMediaType:
description: The Media Type of the request is not supported, it has to be "application/json"
definitions: definitions:
Search: Search:
type: object type: object
@ -2451,7 +2489,9 @@ definitions:
properties: properties:
kind: kind:
type: string type: string
description: The replication policy trigger kind. The valid values are manual, immediate and schedule. description: >-
The replication policy trigger kind. The valid values are manual,
immediate and schedule.
schedule_param: schedule_param:
$ref: '#/definitions/ScheduleParam' $ref: '#/definitions/ScheduleParam'
ScheduleParam: ScheduleParam:
@ -2459,21 +2499,23 @@ definitions:
properties: properties:
type: type:
type: string type: string
description: The schedule type. The valid values are daily and weekly. description: The schedule type. The valid values are daily and weekly.
weekday: weekday:
type: integer type: integer
format: int8 format: int8
description: Optional, only used when the type is weedly. The valid values are 1-7. description: 'Optional, only used when the type is weedly. The valid values are 1-7.'
offtime: offtime:
type: integer type: integer
format: int64 format: int64
description: The time offset with the UTC 00:00 in seconds. description: 'The time offset with the UTC 00:00 in seconds.'
RepFilter: RepFilter:
type: object type: object
properties: properties:
kind: kind:
type: string type: string
description: The replication policy filter kind. The valid values are project, repository and tag. description: >-
The replication policy filter kind. The valid values are project,
repository and tag.
pattern: pattern:
type: string type: string
description: The replication policy filter pattern. description: The replication policy filter pattern.
@ -2505,7 +2547,9 @@ definitions:
description: Reserved field. description: Reserved field.
insecure: insecure:
type: boolean type: boolean
description: Whether or not the certificate will be verified when Harbor tries to access the server. description: >-
Whether or not the certificate will be verified when Harbor tries to
access the server.
creation_time: creation_time:
type: string type: string
description: The create time of the policy. description: The create time of the policy.
@ -2529,7 +2573,9 @@ definitions:
description: The target server password. description: The target server password.
insecure: insecure:
type: boolean type: boolean
description: Whether or not the certificate will be verified when Harbor tries to access the server. description: >-
Whether or not the certificate will be verified when Harbor tries to
access the server.
PingTarget: PingTarget:
type: object type: object
properties: properties:
@ -2548,7 +2594,9 @@ definitions:
description: The target server password. description: The target server password.
insecure: insecure:
type: boolean type: boolean
description: Whether or not the certificate will be verified when Harbor tries to access the server. description: >-
Whether or not the certificate will be verified when Harbor tries to
access the server.
PutTarget: PutTarget:
type: object type: object
properties: properties:
@ -2566,7 +2614,9 @@ definitions:
description: The target server password. description: The target server password.
insecure: insecure:
type: boolean type: boolean
description: Whether or not the certificate will be verified when Harbor tries to access the server. description: >-
Whether or not the certificate will be verified when Harbor tries to
access the server.
HasAdminRole: HasAdminRole:
type: object type: object
properties: properties:
@ -2898,7 +2948,7 @@ definitions:
properties: properties:
auth_mode: auth_mode:
type: string type: string
description: The auth mode of current system, such as "db_auth", "ldap_auth" description: 'The auth mode of current system, such as "db_auth", "ldap_auth"'
email_from: email_from:
type: string type: string
description: The sender name for Email notification. description: The sender name for Email notification.
@ -2916,10 +2966,15 @@ definitions:
description: The username for authenticate against SMTP server. description: The username for authenticate against SMTP server.
email_ssl: email_ssl:
type: boolean type: boolean
description: When it's set to true the system will access Email server via TLS by default. If it's set to false, it still will handle "STARTTLS" from server side. description: >-
When it's set to true the system will access Email server via TLS by
default. If it's set to false, it still will handle "STARTTLS" from
server side.
email_insecure: email_insecure:
type: boolean type: boolean
description: Whether or not the certificate will be verified when Harbor tries to access the email server. description: >-
Whether or not the certificate will be verified when Harbor tries to
access the email server.
ldap_url: ldap_url:
type: string type: string
description: The URL of LDAP server. description: The URL of LDAP server.
@ -2931,10 +2986,12 @@ definitions:
description: The filter for LDAP binding. description: The filter for LDAP binding.
ldap_scope: ldap_scope:
type: integer type: integer
description: 0-LDAP_SCOPE_BASE, 1-LDAP_SCOPE_ONELEVEL, 2-LDAP_SCOPE_SUBTREE description: '0-LDAP_SCOPE_BASE, 1-LDAP_SCOPE_ONELEVEL, 2-LDAP_SCOPE_SUBTREE'
ldap_uid: ldap_uid:
type: string type: string
description: The attribute which is used as identity for the LDAP binding, such as "CN" or "SAMAccountname" description: >-
The attribute which is used as identity for the LDAP binding, such as
"CN" or "SAMAccountname"
ldap_search_dn: ldap_search_dn:
type: string type: string
description: The DN of the user to do the search. description: The DN of the user to do the search.
@ -2943,29 +3000,41 @@ definitions:
description: timeout in seconds for connection to LDAP server. description: timeout in seconds for connection to LDAP server.
project_creation_restriction: project_creation_restriction:
type: string type: string
description: This attribute restricts what users have the permission to create project. It can be "everyone" or "adminonly". description: >-
This attribute restricts what users have the permission to create
project. It can be "everyone" or "adminonly".
self_registration: self_registration:
type: boolean type: boolean
description: Whether the Harbor instance supports self-registration. If it's set to false, admin need to add user to the instance. description: >-
Whether the Harbor instance supports self-registration. If it's set
to false, admin need to add user to the instance.
token_expiration: token_expiration:
type: integer type: integer
description: The expiration time of the token for internal Registry, in minutes. description: 'The expiration time of the token for internal Registry, in minutes.'
verify_remote_cert: verify_remote_cert:
type: boolean type: boolean
description: Whether or not the certificate will be verified when Harbor tries to access a remote Harbor instance for replication. description: >-
Whether or not the certificate will be verified when Harbor tries to
access a remote Harbor instance for replication.
scan_all_policy: scan_all_policy:
type: object type: object
properties: properties:
type: type:
type: string type: string
description: The type of scan all policy, currently the valid values are "none" and "daily" description: >-
The type of scan all policy, currently the valid values are "none"
and "daily"
parameter: parameter:
type: object type: object
properties: properties:
daily_time: daily_time:
type: integer type: integer
description: The offest in seconds of UTC 0 o'clock, only valid when the policy type is "daily" description: >-
description: The parameters of the policy, the values are dependant on the type of the policy. The offest in seconds of UTC 0 o'clock, only valid when the
policy type is "daily"
description: >-
The parameters of the policy, the values are dependant on the type
of the policy.
Replication: Replication:
type: object type: object
properties: properties:
@ -2983,7 +3052,7 @@ definitions:
properties: properties:
policy_id: policy_id:
type: integer type: integer
description: The ID of replication policy description: The ID of replication policy
status: status:
type: string type: string
description: The status of jobs. The only valid value is stop for now. description: The status of jobs. The only valid value is stop for now.

View File

@ -12,7 +12,7 @@ services:
networks: networks:
- harbor - harbor
registry: registry:
image: vmware/registry:2.6.2-photon image: vmware/registry-photon:__reg_version__
container_name: registry container_name: registry
restart: always restart: always
volumes: volumes:
@ -95,7 +95,7 @@ services:
syslog-address: "tcp://127.0.0.1:1514" syslog-address: "tcp://127.0.0.1:1514"
tag: "jobservice" tag: "jobservice"
proxy: proxy:
image: vmware/nginx-photon:1.11.13 image: vmware/nginx-photon:__nginx_version__
container_name: nginx container_name: nginx
restart: always restart: always
volumes: volumes:

View File

@ -265,7 +265,7 @@ else:
storage_provider_name = rcp.get("configuration", "registry_storage_provider_name").strip() storage_provider_name = rcp.get("configuration", "registry_storage_provider_name").strip()
storage_provider_config = rcp.get("configuration", "registry_storage_provider_config").strip() storage_provider_config = rcp.get("configuration", "registry_storage_provider_config").strip()
# yaml requires 1 or more spaces between the key and value # yaml requires 1 or more spaces between the key and value
storage_provider_config = storage_provider_config.replace(":", ": ") storage_provider_config = storage_provider_config.replace(":", ": ", 1)
ui_secret = ''.join(random.choice(string.ascii_letters+string.digits) for i in range(16)) ui_secret = ''.join(random.choice(string.ascii_letters+string.digits) for i in range(16))
jobservice_secret = ''.join(random.choice(string.ascii_letters+string.digits) for i in range(16)) jobservice_secret = ''.join(random.choice(string.ascii_letters+string.digits) for i in range(16))

View File

@ -100,7 +100,9 @@ func schedulePolicy(notification ScanPolicyNotification) error {
OffsetTime: notification.DailyTime, OffsetTime: notification.DailyTime,
}) })
attachTask := task.NewScanAllTask() attachTask := task.NewScanAllTask()
schedulePolicy.AttachTasks(attachTask) if err := schedulePolicy.AttachTasks(attachTask); err != nil {
return err
}
return scheduler.DefaultScheduler.Schedule(schedulePolicy) return scheduler.DefaultScheduler.Schedule(schedulePolicy)
} }

View File

@ -100,7 +100,9 @@ func TestTCPConn(addr string, timeout, interval int) error {
time.Sleep(time.Duration(interval) * time.Second) time.Sleep(time.Duration(interval) * time.Second)
continue continue
} }
conn.Close() if err = conn.Close(); err != nil {
log.Errorf("failed to close the connection: %v", err)
}
success <- 1 success <- 1
break break
} }

View File

@ -28,7 +28,7 @@ func NewLogger(j Job) (*log.Logger, error) {
logFile := j.LogPath() logFile := j.LogPath()
d := filepath.Dir(logFile) d := filepath.Dir(logFile)
if _, err := os.Stat(d); os.IsNotExist(err) { if _, err := os.Stat(d); os.IsNotExist(err) {
err := os.MkdirAll(d, 0755) err := os.MkdirAll(d, 0700)
if err != nil { if err != nil {
log.Errorf("Failed to create directory for log file %s, the error: %v", logFile, err) log.Errorf("Failed to create directory for log file %s, the error: %v", logFile, err)
} }

View File

@ -158,9 +158,11 @@ func (l *Auth) PostAuthenticate(u *models.User) error {
if !Re.MatchString(u.Email) { if !Re.MatchString(u.Email) {
log.Debugf("Not a valid email address: %v, skip to sync", u.Email) log.Debugf("Not a valid email address: %v, skip to sync", u.Email)
} else { } else {
dao.ChangeUserProfile(*u, "Email") if err = dao.ChangeUserProfile(*u, "Email"); err != nil {
u.Email = dbUser.Email
log.Errorf("failed to sync user email: %v", err)
}
} }
u.Email = dbUser.Email
} }
return nil return nil

View File

@ -116,7 +116,9 @@ func main() {
scheduler.DefaultScheduler.Start() scheduler.DefaultScheduler.Start()
//Subscribe the policy change topic. //Subscribe the policy change topic.
notifier.Subscribe(notifier.ScanAllPolicyTopic, &notifier.ScanPolicyNotificationHandler{}) if err = notifier.Subscribe(notifier.ScanAllPolicyTopic, &notifier.ScanPolicyNotificationHandler{}); err != nil {
log.Errorf("failed to subscribe scan all policy change topic: %v", err)
}
//Get policy configuration. //Get policy configuration.
scanAllPolicy := config.ScanAllPolicy() scanAllPolicy := config.ScanAllPolicy()
@ -129,7 +131,10 @@ func main() {
} }
//Send notification to handle first policy change. //Send notification to handle first policy change.
notifier.Publish(notifier.ScanAllPolicyTopic, notifier.ScanPolicyNotification{Type: scanAllPolicy.Type, DailyTime: (int64)(dailyTime)}) if err = notifier.Publish(notifier.ScanAllPolicyTopic,
notifier.ScanPolicyNotification{Type: scanAllPolicy.Type, DailyTime: (int64)(dailyTime)}); err != nil {
log.Errorf("failed to publish scan all policy topic: %v", err)
}
} }
if err := core.Init(); err != nil { if err := core.Init(); err != nil {

View File

@ -89,6 +89,11 @@ if build_type == "ova" :
logger.info("Harbor is not ready after 10 minutes.") logger.info("Harbor is not ready after 10 minutes.")
sys.exit(-1) sys.exit(-1)
logger.info("%s is ready for test now..." % item) logger.info("%s is ready for test now..." % item)
# ----- log harbor version -----
harbor_version = harbor_util.get_harbor_version(item, 'admin', 'Harbor12345')
logger.info("Harbor version: %s ..." % harbor_version)
with open(os.getcwd() + '/build.properties', 'w') as the_file:
the_file.write('harbor_version=%s' % harbor_version)
# ----- execute test cases ----- # ----- execute test cases -----
try: try:

View File

@ -1,6 +1,33 @@
from urllib2 import urlopen from urllib2 import urlopen
import ssl import ssl
import time import time
import os
try:
import json
except ImportError:
import simplejson as json
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
def request(harbor_endpoint, url, method, user, pwd, **kwargs):
url = "https://" + harbor_endpoint + "/api" + url
kwargs.setdefault('headers', kwargs.get('headers', {}))
kwargs['headers']['Accept'] = 'application/json'
if 'body' in kwargs:
kwargs['headers']['Content-Type'] = 'application/json'
kwargs['data'] = json.dumps(kwargs['body'])
del kwargs['body']
resp = requests.request(method, url, verify=False, auth=(user, pwd), **kwargs)
if resp.status_code >= 400:
raise Exception("Error: %s" % resp.text)
try:
body = json.loads(resp.text)
except ValueError:
body = resp.text
return body
# wait for 10 minutes as OVA needs about 7 minutes to startup harbor. # wait for 10 minutes as OVA needs about 7 minutes to startup harbor.
def wait_for_harbor_ready(harbor_endpoint, timeout=600): def wait_for_harbor_ready(harbor_endpoint, timeout=600):
@ -20,4 +47,7 @@ def wait_for_harbor_ready(harbor_endpoint, timeout=600):
time.sleep(interval) time.sleep(interval)
continue continue
timeout -= interval timeout -= interval
time.sleep(interval) time.sleep(interval)
def get_harbor_version(harbor_endpoint, harbor_user, harbor_pwd):
return request(harbor_endpoint, '/systeminfo', 'get', harbor_user, harbor_pwd)['harbor_version']