Commit 2b4ad5ec authored by Stan Hu's avatar Stan Hu

Merge branch 'ce-to-ee-2018-11-13' into 'master'

CE upstream - 2018-11-13 17:21 UTC

Closes gitlab-ce#53919

See merge request gitlab-org/gitlab-ee!8429
parents a3a68f7d 0510a400
<script>
import { GlTooltipDirective, GlLink, GlButton } from '@gitlab-org/gitlab-ui';
import CiIconBadge from './ci_badge_link.vue';
import TimeagoTooltip from './time_ago_tooltip.vue';
import tooltip from '../directives/tooltip';
import UserAvatarImage from './user_avatar/user_avatar_image.vue';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
/**
* Renders header component for job and pipeline page based on UI mockups
......@@ -16,9 +17,12 @@ export default {
CiIconBadge,
TimeagoTooltip,
UserAvatarImage,
GlLink,
GlButton,
LoadingButton,
},
directives: {
tooltip,
GlTooltip: GlTooltipDirective,
},
props: {
status: {
......@@ -98,8 +102,8 @@ export default {
by
<template v-if="user">
<a
v-tooltip
<gl-link
v-gl-tooltip
:href="user.path"
:title="user.email"
class="js-user-link commit-committer-link"
......@@ -113,7 +117,7 @@ export default {
/>
{{ user.name }}
</a>
</gl-link>
<span
v-if="user.status_tooltip_html"
v-html="user.status_tooltip_html"></span>
......@@ -127,16 +131,16 @@ export default {
<template
v-for="(action, i) in actions"
>
<a
<gl-link
v-if="action.type === 'link'"
:key="i"
:href="action.path"
:class="action.cssClass"
>
{{ action.label }}
</a>
</gl-link>
<a
<gl-link
v-else-if="action.type === 'ujs-link'"
:key="i"
:href="action.path"
......@@ -145,31 +149,24 @@ export default {
rel="nofollow"
>
{{ action.label }}
</a>
</gl-link>
<button
<loading-button
v-else-if="action.type === 'button'"
:key="i"
:loading="action.isLoading"
:disabled="action.isLoading"
:class="action.cssClass"
type="button"
container-class="d-inline"
:label="action.label"
@click="onClickAction(action)"
>
{{ action.label }}
<i
v-show="action.isLoading"
class="fa fa-spin fa-spinner"
aria-hidden="true"
>
</i>
</button>
/>
</template>
</section>
<button
<gl-button
v-if="hasSidebarButton"
id="toggleSidebar"
type="button"
class="btn btn-default d-block d-sm-none
class="d-block d-sm-none
sidebar-toggle-btn js-sidebar-build-toggle js-sidebar-build-toggle-header"
@click="onClickSidebarButton"
>
......@@ -179,6 +176,6 @@ sidebar-toggle-btn js-sidebar-build-toggle js-sidebar-build-toggle-header"
aria-labelledby="toggleSidebar"
>
</i>
</button>
</gl-button>
</header>
</template>
......@@ -37,6 +37,6 @@
= link_to 'Reopen', merge_request_path(@merge_request, merge_request: { state_event: :reopen }), method: :put, class: 'reopen-mr-link', title: 'Reopen merge request'
- if can_update_merge_request
= link_to 'Edit', edit_project_merge_request_path(@project, @merge_request), class: "d-none d-sm-none d-md-block btn btn-grouped js-issuable-edit"
= link_to 'Edit', edit_project_merge_request_path(@project, @merge_request), class: "d-none d-sm-none d-md-block btn btn-grouped js-issuable-edit qa-edit-button"
= render 'shared/issuable/close_reopen_button', issuable: @merge_request, can_update: can_update_merge_request, can_reopen: can_update_merge_request
......@@ -55,8 +55,8 @@ provide a list of URLs to test, please consult
TIP: **Tip:**
For [GitLab Premium](https://about.gitlab.com/pricing/) users, key metrics are automatically
extracted and shown right in the merge request widget. Learn more about
[Browser Performance Testing](../../user/project/merge_requests/browser_performance_testing.md).
extracted and shown right in the merge request widget.
[Learn more on Browser Performance Testing in merge requests](../../user/project/merge_requests/browser_performance_testing.md).
## Performance testing on Review Apps
......
......@@ -75,9 +75,10 @@ code_quality:
paths: [gl-code-quality-report.json]
```
Alternatively the job name could be `codeclimate` or `codequality` and the artifact name could be
`codeclimate.json`. These names have been deprecated with GitLab 11.0 and may be removed
in next major release, GitLab 12.0.
Alternatively the job name could be `codeclimate` or `codequality`
and the artifact name could be `codeclimate.json`.
These names have been deprecated with GitLab 11.0
and may be removed in next major release, GitLab 12.0.
For GitLab 10.3 and earlier, the job should look like:
......
......@@ -1337,7 +1337,7 @@ concatenated into a single file. Use a filename pattern (`junit: rspec-*.xml`),
an array of filenames (`junit: [rspec-1.xml, rspec-2.xml, rspec-3.xml]`), or a
combination thereof (`junit: [rspec.xml, test-results/TEST-*.xml]`).
#### `artifacts:reports:codequality`
#### `artifacts:reports:codequality` **[STARTER]**
> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
......@@ -1347,7 +1347,7 @@ as artifacts.
The collected Code Quality report will be uploaded to GitLab as an artifact and will
be automatically shown in merge requests.
#### `artifacts:reports:sast`
#### `artifacts:reports:sast` **[ULTIMATE]**
> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
......@@ -1358,7 +1358,7 @@ The collected SAST report will be uploaded to GitLab as an artifact and will
be automatically shown in merge requests, pipeline view and provide data for security
dashboards.
#### `artifacts:reports:dependency_scanning`
#### `artifacts:reports:dependency_scanning` **[ULTIMATE]**
> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
......@@ -1369,7 +1369,7 @@ The collected Dependency Scanning report will be uploaded to GitLab as an artifa
be automatically shown in merge requests, pipeline view and provide data for security
dashboards.
#### `artifacts:reports:container_scanning`
#### `artifacts:reports:container_scanning` **[ULTIMATE]**
> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
......@@ -1380,7 +1380,7 @@ The collected Container Scanning report will be uploaded to GitLab as an artifac
be automatically shown in merge requests, pipeline view and provide data for security
dashboards.
#### `artifacts:reports:dast`
#### `artifacts:reports:dast` **[ULTIMATE]**
> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
......@@ -1391,7 +1391,7 @@ The collected DAST report will be uploaded to GitLab as an artifact and will
be automatically shown in merge requests, pipeline view and provide data for security
dashboards.
#### `artifacts:reports:license_management`
#### `artifacts:reports:license_management` **[ULTIMATE]**
> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
......@@ -1402,7 +1402,7 @@ The collected License Management report will be uploaded to GitLab as an artifac
be automatically shown in merge requests, pipeline view and provide data for security
dashboards.
#### `artifacts:reports:performance`
#### `artifacts:reports:performance` **[PREMIUM]**
> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
......
......@@ -119,10 +119,20 @@ This also applies to views.
### EE features based on CE features
For features that build on existing CE features, write a module in the
`EE` namespace and `prepend` it in the CE class. This makes conflicts
less likely to happen during CE to EE merges because only one line is
added to the CE class - the `prepend` line.
For features that build on existing CE features, write a module in the `EE`
namespace and `prepend` it in the CE class, on the last line of the file that
the class resides in. This makes conflicts less likely to happen during CE to EE
merges because only one line is added to the CE class - the `prepend` line. For
example, to prepend a module into the `User` class you would use the following
approach:
```ruby
class User < ActiveRecord::Base
# ... lots of code here ...
end
User.prepend(EE::User)
```
Since the module would require an `EE` namespace, the file should also be
put in an `ee/` sub-directory. For example, we want to extend the user model
......@@ -231,7 +241,6 @@ the existing file:
```ruby
class ApplicationController < ActionController::Base
prepend EE::ApplicationController
# ...
def after_sign_out_path_for(resource)
......@@ -240,6 +249,8 @@ class ApplicationController < ActionController::Base
# ...
end
ApplicationController.prepend(EE::ApplicationController)
```
And create a new file in the `ee/` sub-directory with the altered
......@@ -533,8 +544,6 @@ module API
end
end
prepend EE::API::MergeRequests
params :optional_params do
# CE specific params go here...
......@@ -542,6 +551,8 @@ module API
end
end
end
API::MergeRequests.prepend(EE::API::MergeRequests)
```
And then we could override it in EE module:
......@@ -582,10 +593,10 @@ module API
authorize_read_builds!
end
end
prepend EE::API::JobArtifacts
end
end
API::JobArtifacts.prepend(EE::API::JobArtifacts)
```
And then we can follow regular object-oriented practices to override it:
......@@ -626,8 +637,6 @@ module API
end
end
prepend EE::API::MergeRequests
put ':id/merge_requests/:merge_request_iid/merge' do
merge_request = find_project_merge_request(params[:merge_request_iid])
......@@ -639,6 +648,8 @@ module API
end
end
end
API::MergeRequests.prepend(EE::API::MergeRequests)
```
Note that `update_merge_request_ee` doesn't do anything in CE, but
......@@ -676,27 +687,37 @@ or not we really need to extend it from EE. For now we're not using it much.
Sometimes we need to use different arguments for a particular API route, and we
can't easily extend it with an EE module because Grape has different context in
different blocks. In order to overcome this, we could use class methods from the
API class.
different blocks. In order to overcome this, we need to move the data to a class
method that resides in a separate module or class. This allows us to extend that
module or class before its data is used, without having to place a `prepend` in
the middle of CE code.
For example, in one place we need to pass an extra argument to
`at_least_one_of` so that the API could consider an EE-only argument as the
least argument. This is not quite beautiful but it's working:
least argument. We would approach this as follows:
```ruby
# api/merge_requests/parameters.rb
module API
class MergeRequests < Grape::API
def self.update_params_at_least_one_of
%i[
assignee_id
description
]
module Parameters
def self.update_params_at_least_one_of
%i[
assignee_id
description
]
end
end
end
end
prepend EE::API::MergeRequests
API::MergeRequests::Parameters.prepend(EE::API::MergeRequests::Parameters)
# api/merge_requests.rb
module API
class MergeRequests < Grape::API
params do
at_least_one_of(*::API::MergeRequests.update_params_at_least_one_of)
at_least_one_of(*Parameters.update_params_at_least_one_of)
end
end
end
......@@ -708,16 +729,18 @@ And then we could easily extend that argument in the EE class method:
module EE
module API
module MergeRequests
extend ActiveSupport::Concern
module Parameters
extend ActiveSupport::Concern
class_methods do
extend ::Gitlab::Utils::Override
class_methods do
extend ::Gitlab::Utils::Override
override :update_params_at_least_one_of
def update_params_at_least_one_of
super.push(*%i[
squash
])
override :update_params_at_least_one_of
def update_params_at_least_one_of
super.push(*%i[
squash
])
end
end
end
end
......@@ -728,6 +751,78 @@ end
It could be annoying if we need this for a lot of routes, but it might be the
simplest solution right now.
This approach can also be used when models define validations that depend on
class methods. For example:
```ruby
# app/models/identity.rb
class Identity < ActiveRecord::Base
def self.uniqueness_scope
[:provider]
end
prepend EE::Identity
validates :extern_uid,
allow_blank: true,
uniqueness: { scope: uniqueness_scope, case_sensitive: false }
end
# ee/app/models/ee/identity.rb
module EE
module Identity
extend ActiveSupport::Concern
class_methods do
extend ::Gitlab::Utils::Override
def uniqueness_scope
[*super, :saml_provider_id]
end
end
end
end
```
Instead of taking this approach, we would refactor our code into the following:
```ruby
# ee/app/models/ee/identity/uniqueness_scopes.rb
module EE
module Identity
module UniquenessScopes
extend ActiveSupport::Concern
class_methods do
extend ::Gitlab::Utils::Override
def uniqueness_scope
[*super, :saml_provider_id]
end
end
end
end
end
# app/models/identity/uniqueness_scopes.rb
class Identity < ActiveRecord::Base
module UniquenessScopes
def self.uniqueness_scope
[:provider]
end
end
end
Identity::UniquenessScopes.prepend(EE::Identity::UniquenessScopes)
# app/models/identity.rb
class Identity < ActiveRecord::Base
validates :extern_uid,
allow_blank: true,
uniqueness: { scope: Identity::UniquenessScopes.scopes, case_sensitive: false }
end
```
### Code in `spec/`
When you're testing EE-only features, avoid adding examples to the
......
......@@ -2,7 +2,7 @@
## Monitoring
We have a performance dashboard available in one of our [grafana instances](https://performance.gprd.gitlab.com/dashboard/db/sitespeed-page-summary?orgId=1). This dashboard automatically aggregates metric data from [sitespeed.io](https://sitespeed.io) every 6 hours. These changes are displayed after a set number of pages are aggregated.
We have a performance dashboard available in one of our [grafana instances](https://dashboards.gitlab.net/d/1EBTz3Dmz/sitespeed-page-summary?orgId=1). This dashboard automatically aggregates metric data from [sitespeed.io](https://sitespeed.io) every 6 hours. These changes are displayed after a set number of pages are aggregated.
These pages can be found inside a text file in the gitlab-build-images [repository](https://gitlab.com/gitlab-org/gitlab-build-images) called [gitlab.txt](https://gitlab.com/gitlab-org/gitlab-build-images/blob/master/scripts/gitlab.txt)
Any frontend engineer can contribute to this dashboard. They can contribute by adding or removing urls of pages from this text file. Please have a [frontend monitoring expert](https://about.gitlab.com/team) review your changes before assigning to a maintainer of the `gitlab-build-images` project. The changes will go live on the next scheduled run after the changes are merged into `master`.
......
# Overview of Frontend Testing
## Types of tests in our codebase
Tests relevant for frontend development can be found at two places:
- `spec/javascripts/` which are run by Karma and contain
- [frontend unit tests](#frontend-unit-tests)
- [frontend component tests](#frontend-component-tests)
- [frontend integration tests](#frontend-integration-tests)
- `spec/features/` which are run by RSpec and contain
- [feature tests](#feature-tests)
In addition there were feature tests in `features/` run by Spinach in the past.
These have been removed from our codebase in May 2018 ([#23036](https://gitlab.com/gitlab-org/gitlab-ce/issues/23036)).
See also:
* **RSpec**
* **[Ruby unit tests](#ruby-unit-tests-spec-rb)** for models, controllers, helpers, etc. (`/spec/**/*.rb`)
* **[Full feature tests](#full-feature-tests-spec-features-rb)** (`/spec/features/**/*.rb`)
* **[Karma](#karma-tests-spec-javascripts-js)** (`/spec/javascripts/**/*.js`)
* <s>Spinach</s> — These have been removed from our codebase in May 2018. (`/features/`)
- [old testing guide](../../testing_guide/frontend_testing.html)
- [notes on testing Vue components](../../fe_guide/vue.html#testing-vue-components)
## RSpec: Ruby unit tests `/spec/**/*.rb`
## Frontend unit tests
These tests are meant to unit test the ruby models, controllers and helpers.
Unit tests are on the lowest abstraction level and typically test functionality that is not directly perceivable by a user.
### When do we write/update these tests?
### When to use unit tests
Whenever we create or modify any Ruby models, controllers or helpers we add/update corresponding tests.
<details>
<summary>exported functions and classes</summary>
Anything that is exported can be reused at various places in a way you have no control over.
Therefore it is necessary to document the expected behavior of the public interface with tests.
</details>
---
<details>
<summary>Vuex actions</summary>
Any Vuex action needs to work in a consistent way independent of the component it is triggered from.
</details>
## RSpec: Full feature tests `/spec/features/**/*.rb`
<details>
<summary>Vuex mutations</summary>
For complex Vuex mutations it helps to identify the source of a problem by separating the tests from other parts of the Vuex store.
</details>
Full feature tests will load a full app environment and allow us to test things like rendering DOM, interacting with links and buttons, testing the outcome of those interactions through multiple pages if necessary. These are also called end-to-end tests but should not be confused with QA end-to-end tests (`package-and-qa` manual pipeline job).
### When *not* to use unit tests
### When do we write/update these tests?
<details>
<summary>non-exported functions or classes</summary>
Anything that is not exported from a module can be considered private or an implementation detail and doesn't need to be tested.
</details>
When we add a new feature, we write at least two tests covering the success and the failure scenarios.
<details>
<summary>constants</summary>
Testing the value of a constant would mean to copy it.
This results in extra effort without additional confidence that the value is correct.
</details>
<details>
<summary>Vue components</summary>
Computed properties, methods, and lifecycle hooks can be considered an implementation detail of components and don't need to be tested.
They are implicitly covered by component tests.
The <a href="https://vue-test-utils.vuejs.org/guides/#getting-started">official Vue guidelines</a> suggest the same.
</details>
### What to mock in unit tests
<details>
<summary>state of the class under test</summary>
Modifying the state of the class under test directly rather than using methods of the class avoids side-effects in test setup.
</details>
<details>
<summary>other exported classes</summary>
Every class needs to be tested in isolation to prevent test scenarios from growing exponentially.
</details>
<details>
<summary>single DOM elements if passed as parameters</summary>
For tests that only operate on single DOM elements rather than a whole page, creating these elements is cheaper than loading a whole HTML fixture.
</details>
<details>
<summary>all server requests</summary>
When running frontend unit tests, the backend may not be reachable.
Therefore all outgoing requests need to be mocked.
</details>
<details>
<summary>asynchronous background operations</summary>
Background operations cannot be stopped or waited on, so they will continue running in the following tests and cause side effects.
</details>
### What *not* to mock in unit tests
<details>
<summary>non-exported functions or classes</summary>
Everything that is not exported can be considered private to the module and will be implicitly tested via the exported classes / functions.
</details>
<details>
<summary>methods of the class under test</summary>
By mocking methods of the class under test, the mocks will be tested and not the real methods.
</details>
<details>
<summary>utility functions (pure functions, or those that only modify parameters)</summary>
If a function has no side effects because it has no state, it is safe to not mock it in tests.
</details>
<details>
<summary>full HTML pages</summary>
Loading the HTML of a full page slows down tests, so it should be avoided in unit tests.
</details>
## Frontend component tests
Component tests cover the state of a single component that is perceivable by a user depending on external signals such as user input, events fired from other components, or application state.
### When to use component tests
- Vue components
### When *not* to use component tests
<details>
<summary>Vue applications</summary>
Vue applications may contain many components.
Testing them on a component level requires too much effort.
Therefore they are tested on frontend integration level.
</details>
<details>
<summary>HAML templates</summary>
HAML templates contain only Markup and no frontend-side logic.
Therefore they are not complete components.
</details>
### What to mock in component tests
<details>
<summary>DOM</summary>
Operating on the real DOM is significantly slower than on the virtual DOM.
</details>
<details>
<summary>properties and state of the component under test</summary>
Similarly to testing classes, modifying the properties directly (rather than relying on methods of the component) avoids side-effects.
</details>
<details>
<summary>Vuex store</summary>
To avoid side effects and keep component tests simple, Vuex stores are replaced with mocks.
</details>
<details>
<summary>all server requests</summary>
Similar to unit tests, when running component tests, the backend may not be reachable.
Therefore all outgoing requests need to be mocked.
</details>
<details>
<summary>asynchronous background operations</summary>
Similar to unit tests, background operations cannot be stopped or waited on, so they will continue running in the following tests and cause side effects.
</details>
<details>
<summary>child components</summary>
Every component is tested individually, so child components are mocked.
See also <a href="https://vue-test-utils.vuejs.org/api/#shallowmount">shallowMount()</a>
</details>
### What *not* to mock in component tests
<details>
<summary>methods or computed properties of the component under test</summary>
By mocking part of the component under test, the mocks will be tested and not the real component.
</details>
<details>
<summary>functions and classes independent from Vue</summary>
All plain JavaScript code is already covered by unit tests and needs not to be mocked in component tests.
</details>
## Frontend integration tests
Integration tests cover the interaction between all components on a single page.
Their abstraction level is comparable to how a user would interact with the UI.
### When to use integration tests
<details>
<summary>page bundles (<code>index.js</code> files in <code>app/assets/javascripts/pages/</code>)</summary>
Testing the page bundles ensures the corresponding frontend components integrate well.
</details>
<details>
<summary>Vue applications outside of page bundles</summary>
Testing Vue applications as a whole ensures the corresponding frontend components integrate well.
</details>
### What to mock in integration tests
<details>
<summary>HAML views (use fixtures instead)</summary>
Rendering HAML views requires a Rails environment including a running database which we cannot rely on in frontend tests.
</details>
<details>
<summary>all server requests</summary>
Similar to unit and component tests, when running component tests, the backend may not be reachable.
Therefore all outgoing requests need to be mocked.
</details>
<details>
<summary>asynchronous background operations that are not perceivable on the page</summary>
Background operations that affect the page need to be tested on this level.
All other background operations cannot be stopped or waited on, so they will continue running in the following tests and cause side effects.
</details>
### What *not* to mock in integration tests
<details>
<summary>DOM</summary>
Testing on the real DOM ensures our components work in the environment they are meant for.
Part of this will be delegated to <a href="https://gitlab.com/gitlab-org/quality/team-tasks/issues/45">cross-browser testing</a>.
</details>
<details>
<summary>properties or state of components</summary>
On this level, all tests can only perform actions a user would do.
For example to change the state of a component, a click event would be fired.
</details>
<details>
<summary>Vuex stores</summary>
When testing the frontend code of a page as a whole, the interaction between Vue components and Vuex stores is covered as well.
<details>
## Feature tests
In contrast to [frontend integration tests](#frontend-integration-tests), feature tests make requests against the real backend instead of using fixtures.
This also implies that database queries are executed which makes this category significantly slower.
### When to use feature tests
- use cases that require a backend and cannot be tested using fixtures
- behavior that is not part of a page bundle but defined globally
### Relevant notes
......@@ -48,33 +265,9 @@ wait_for_requests
expect(page).not_to have_selector('.card')
```
---
## Karma tests `/spec/javascripts/**/*.js`
These are the more frontend-focused, at the moment. They're **faster** than `rspec` and make for very quick testing of frontend components.
### When do we write/update these tests?
When we add/update a method/action/mutation to Vue or Vuex, we write karma tests to ensure the logic we wrote doesn't break. We should, however, refrain from writing tests that double-test Vue's internal features.
### Relevant notes
Karma tests are run against a virtual DOM.
## Test helpers
To populate the DOM, we can use fixtures to fake the generation of HTML instead of having Rails do that.
Be sure to check the [best practices for karma tests](../../testing_guide/frontend_testing.html#best-practices).
### Vue and Vuex
Test as much as possible without double-testing Vue's internal features, as mentioned above.
Make sure to test computedProperties, mutations, actions. Run the action and test that the proper mutations are committed.
Also check these [notes on testing Vue components](../../fe_guide/vue.html#testing-vue-components).
#### Vuex Helper: `testAction`
### Vuex Helper: `testAction`
We have a helper available to make testing actions easier, as per [official documentation](https://vuex.vuejs.org/en/testing.html):
......@@ -97,7 +290,7 @@ testAction(
Check an example in [spec/javascripts/ide/stores/actions_spec.jsspec/javascripts/ide/stores/actions_spec.js](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/spec/javascripts/ide/stores/actions_spec.js).
#### Vue Helper: `mountComponent`
### Vue Helper: `mountComponent`
To make mounting a Vue component easier and more readable, we have a few helpers available in `spec/helpers/vue_mount_component_helper`.
......@@ -133,6 +326,7 @@ afterEach(() => {
vm.$destroy();
});
```
## Testing with older browsers
Some regressions only affect a specific browser version. We can install and test in particular browsers with either Firefox or Browserstack using the following steps:
......
---
author: Joshua Lambert
author_gitlab: joshlambert
level: intermediate
article_type: tutorial
date: 2018-06-05
---
# Connecting and deploying to an Amazon EKS cluster
## Introduction
In this tutorial, we will show how easy it is to integrate an [Amazon EKS](https://aws.amazon.com/eks/) cluster with GitLab, and begin deploying applications.
In this tutorial, we will show how to integrate an [Amazon EKS](https://aws.amazon.com/eks/) cluster with GitLab, and begin deploying applications.
For an end-to-end walkthrough we will:
......@@ -21,7 +13,7 @@ For an end-to-end walkthrough we will:
You will need:
1. An account on GitLab, like [GitLab.com](https://gitlab.com)
1. An Amazon EKS cluster
1. An Amazon EKS cluster (with worker nodes properly configured)
1. `kubectl` [installed and configured for access to the EKS cluster](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html#get-started-kubectl)
If you don't have an Amazon EKS cluster, one can be created by following [the EKS getting started guide](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html).
......@@ -38,26 +30,103 @@ Give the project a name, and then select `Create project`.
![Create Project](img/create_project.png)
## Connecting the EKS cluster
## Configuring and connecting the EKS cluster
From the left side bar, hover over `Operations` and select `Kubernetes`, then click on `Add Kubernetes cluster`, and finally `Add an existing Kubernetes cluster`.
A few details from the EKS cluster will be required to connect it to GitLab.
1. A valid Kubernetes certificate and token are needed to authenticate to the EKS cluster. A pair is created by default, which can be used. Open a shell and use `kubectl` to retrieve them:
* List the secrets with `kubectl get secrets`, and one should named similar to `default-token-xxxxx`. Copy that token name for use below.
* Get the certificate with `kubectl get secret <secret name> -o jsonpath="{['data']['ca\.crt']}" | base64 -D`
* Retrieve the token with `kubectl get secret <secret name> -o jsonpath="{['data']['token']}" | base64 -D`.
1. **Retrieve the certificate**: A valid Kubernetes certificate is needed to authenticate to the EKS cluster. We will use the certificate created by default. Open a shell and use `kubectl` to retrieve it:
- List the secrets with `kubectl get secrets`, and one should named similar to `default-token-xxxxx`. Copy that token name for use below.
- Get the certificate with `kubectl get secret <secret name> -o jsonpath="{['data']['ca\.crt']}" | base64 -D`
1. **Create admin token**: A `cluster-admin` token is required to install and manage Helm Tiller. GitLab establishes mutual SSL auth with Helm Tiller and creates limited service accounts for each application. To create the token we will create an admin service account as follows:
1. Create a file called `eks-admin-service-account.yaml` with the text below:
```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: eks-admin
namespace: kube-system
```
2. Apply the service account to your cluster:
```bash
kubectl apply -f eks-admin-service-account.yaml
```
Output:
```bash
serviceaccount "eks-admin" created
```
3. Create a file called `eks-admin-cluster-role-binding.yaml` with the text below:
```yaml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: eks-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: eks-admin
namespace: kube-system
```
4. Apply the cluster role binding to your cluster:
```bash
kubectl apply -f eks-admin-cluster-role-binding.yaml
```
Output:
```bash
clusterrolebinding "eks-admin" created
```
5. Retrieve the token for the `eks-admin` service account. Copy the `<authentication_token>` value from the output.
```bash
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep eks-admin | awk '{print $1}')
```
Output:
```yaml
Name: eks-admin-token-b5zv4
Namespace: kube-system
Labels: <none>
Annotations: kubernetes.io/service-account.name=eks-admin
kubernetes.io/service-account.uid=bcfe66ac-39be-11e8-97e8-026dce96b6e8
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1025 bytes
namespace: 11 bytes
token: <authentication_token>
```
1. The API server endpoint is also required, so GitLab can connect to the cluster. This is displayed on the AWS EKS console, when viewing the EKS cluster details.
You now have all the information needed to connect the EKS cluster:
* Kubernetes cluster name: Provide a name for the cluster to identify it within GitLab.
* Environment scope: Leave this as `*` for now, since we are only connecting a single cluster.
* API URL: Paste in the API server endpoint retrieved above.
* CA Certificate: Paste the certificate data from the earlier step, as-is.
* Paste the token value.
* Project namespace: This can be left blank to accept the default namespace, based on the project name.
- Kubernetes cluster name: Provide a name for the cluster to identify it within GitLab.
- Environment scope: Leave this as `*` for now, since we are only connecting a single cluster.
- API URL: Paste in the API server endpoint retrieved above.
- CA Certificate: Paste the certificate data from the earlier step, as-is.
- Paste the admin token value.
- Project namespace: This can be left blank to accept the default namespace, based on the project name.
![Add Cluster](img/add_cluster.png)
......@@ -65,9 +134,11 @@ Click on `Add Kubernetes cluster`, the cluster is now connected to GitLab. At th
If you would like to utilize your own CI/CD scripts to deploy to the cluster, you can stop here.
## Disable Role-Based Access Control (RBAC)
## Disable Role-Based Access Control (RBAC) - Optional
When connecting a cluster via GitLab integration, you may specify whether the cluster is RBAC-enabled or not. This will affect how GitLab interacts with the cluster for certain operations. If you **did not** check the "RBAC-enabled cluster" checkbox at creation time, GitLab will assume RBAC is disabled for your cluster when interacting with it. If so, you must disable RBAC on your cluster for the integration to work properly.
Presently, Auto DevOps and one-click app installs do not support [Kubernetes role-based access control](https://kubernetes.io/docs/reference/access-authn-authz/rbac/). Support is [being worked on](https://gitlab.com/groups/gitlab-org/-/epics/136), but in the interim RBAC must be disabled to utilize for these features.
![rbac](img/rbac.png)
> **Note**: Disabling RBAC means that any application running in the cluster, or user who can authenticate to the cluster, has full API access. This is a [security concern](https://docs.gitlab.com/ee/user/project/clusters/#security-implications), and may not be desirable.
......
......@@ -57,6 +57,10 @@ module QA
element :labels_block
end
view 'app/views/projects/merge_requests/_mr_title.html.haml' do
element :edit_button
end
def fast_forward_possible?
!has_text?('Fast-forward merge is not possible')
end
......@@ -165,6 +169,10 @@ module QA
all_elements(:discussion_reply).last.click
fill_element :reply_input, reply_text
end
def edit!
click_element :edit_button
end
end
end
end
......
......@@ -11,7 +11,9 @@ module QA
:target_branch,
:assignee,
:milestone,
:labels
:labels,
:file_name,
:file_content
attribute :project do
Project.fabricate! do |resource|
......@@ -35,8 +37,8 @@ module QA
resource.branch_name = target_branch
resource.remote_branch = source_branch
resource.new_branch = false
resource.file_name = "added_file.txt"
resource.file_content = "File Added"
resource.file_name = file_name
resource.file_content = file_content
end
end
......@@ -48,6 +50,8 @@ module QA
@assignee = nil
@milestone = nil
@labels = []
@file_name = "added_file.txt"
@file_content = "File Added"
end
def fabricate!
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment