Skip to content
Snippets Groups Projects
Commit 427b23c1 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 6d60f910
No related branches found
No related tags found
No related merge requests found
Showing
with 241 additions and 29 deletions
1.10.0
1.11.0
<script>
import { createNamespacedHelpers, mapState, mapActions } from 'vuex';
import { sprintf, s__ } from '~/locale';
import ClusterFormDropdown from './cluster_form_dropdown.vue';
import RegionDropdown from './region_dropdown.vue';
import RoleNameDropdown from './role_name_dropdown.vue';
import SecurityGroupDropdown from './security_group_dropdown.vue';
import SubnetDropdown from './subnet_dropdown.vue';
import VpcDropdown from './vpc_dropdown.vue';
 
const { mapState: mapRegionsState, mapActions: mapRegionsActions } = createNamespacedHelpers(
'regions',
);
const { mapState: mapVpcsState, mapActions: mapVpcActions } = createNamespacedHelpers('vpcs');
const { mapState: mapSubnetsState, mapActions: mapSubnetActions } = createNamespacedHelpers(
'subnets',
);
 
export default {
components: {
ClusterFormDropdown,
RegionDropdown,
RoleNameDropdown,
SecurityGroupDropdown,
SubnetDropdown,
VpcDropdown,
},
computed: {
...mapState(['selectedRegion']),
...mapState(['selectedRegion', 'selectedVpc', 'selectedSubnet']),
...mapRegionsState({
regions: 'items',
isLoadingRegions: 'isLoadingItems',
loadingRegionsError: 'loadingItemsError',
}),
...mapVpcsState({
vpcs: 'items',
isLoadingVpcs: 'isLoadingItems',
loadingVpcsError: 'loadingItemsError',
}),
...mapSubnetsState({
subnets: 'items',
isLoadingSubnets: 'isLoadingItems',
loadingSubnetsError: 'loadingItemsError',
}),
vpcDropdownDisabled() {
return !this.selectedRegion;
},
subnetDropdownDisabled() {
return !this.selectedVpc;
},
vpcDropdownHelpText() {
return sprintf(
s__(
'ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{startLink}Amazon Web Services%{endLink}.',
),
{
startLink:
'<a href="https://console.aws.amazon.com/vpc/home?#vpc" target="_blank" rel="noopener noreferrer">',
endLink: '</a>',
},
false,
);
},
subnetDropdownHelpText() {
return sprintf(
s__(
'ClusterIntegration|Choose the %{startLink}subnets%{endLink} in your VPC where your worker nodes will run.',
),
{
startLink:
'<a href="https://console.aws.amazon.com/vpc/home?#subnets" target="_blank" rel="noopener noreferrer">',
endLink: '</a>',
},
false,
);
},
},
mounted() {
this.fetchRegions();
},
methods: {
...mapActions(['setRegion']),
...mapRegionsActions({
fetchRegions: 'fetchItems',
}),
...mapActions(['setRegion', 'setVpc', 'setSubnet']),
...mapRegionsActions({ fetchRegions: 'fetchItems' }),
...mapVpcActions({ fetchVpcs: 'fetchItems' }),
...mapSubnetActions({ fetchSubnets: 'fetchItems' }),
setRegionAndFetchVpcs(region) {
this.setRegion({ region });
this.fetchVpcs({ region });
},
setVpcAndFetchSubnets(vpc) {
this.setVpc({ vpc });
this.fetchSubnets({ vpc });
},
},
};
</script>
Loading
Loading
@@ -54,8 +107,52 @@ export default {
:regions="regions"
:error="loadingRegionsError"
:loading="isLoadingRegions"
@input="setRegion({ region: $event })"
@input="setRegionAndFetchVpcs($event)"
/>
</div>
<div class="form-group">
<label class="label-bold" name="eks-vpc" for="eks-vpc">{{
s__('ClusterIntegration|VPC')
}}</label>
<cluster-form-dropdown
field-id="eks-vpc"
field-name="eks-vpc"
:input="selectedVpc"
:items="vpcs"
:loading="isLoadingVpcs"
:disabled="vpcDropdownDisabled"
:disabled-text="s__('ClusterIntegration|Select a region to choose a VPC')"
:loading-text="s__('ClusterIntegration|Loading VPCs')"
:placeholder="s__('ClusterIntergation|Select a VPC')"
:search-field-placeholder="s__('ClusterIntegration|Search VPCs')"
:empty-text="s__('ClusterIntegration|No VPCs found')"
:has-errors="loadingVpcsError"
:error-message="s__('ClusterIntegration|Could not load VPCs for the selected region')"
@input="setVpcAndFetchSubnets($event)"
/>
<p class="form-text text-muted" v-html="vpcDropdownHelpText"></p>
</div>
<div class="form-group">
<label class="label-bold" name="eks-subnet" for="eks-subnet">{{
s__('ClusterIntegration|Subnet')
}}</label>
<cluster-form-dropdown
field-id="eks-subnet"
field-name="eks-subnet"
:input="selectedSubnet"
:items="subnets"
:loading="isLoadingSubnets"
:disabled="subnetDropdownDisabled"
:disabled-text="s__('ClusterIntegration|Select a VPC to choose a subnet')"
:loading-text="s__('ClusterIntegration|Loading subnets')"
:placeholder="s__('ClusterIntergation|Select a subnet')"
:search-field-placeholder="s__('ClusterIntegration|Search subnets')"
:empty-text="s__('ClusterIntegration|No subnet found')"
:has-errors="loadingSubnetsError"
:error-message="s__('ClusterIntegration|Could not load subnets for the selected VPC')"
@input="setSubnet({ subnet: $event })"
/>
<p class="form-text text-muted" v-html="subnetDropdownHelpText"></p>
</div>
</form>
</template>
Loading
Loading
@@ -17,4 +17,45 @@ export const fetchRegions = () =>
.send();
});
 
export const fetchVpcs = () =>
new Promise((resolve, reject) => {
const ec2 = new EC2();
ec2
.describeVpcs()
.on('success', ({ data: { Vpcs: vpcs } }) => {
const transformedVpcs = vpcs.map(({ VpcId: id }) => ({ id, name: id }));
resolve(transformedVpcs);
})
.on('error', error => {
reject(error);
})
.send();
});
export const fetchSubnets = ({ vpc }) =>
new Promise((resolve, reject) => {
const ec2 = new EC2();
ec2
.describeSubnets({
Filters: [
{
Name: 'vpc-id',
Values: [vpc.id],
},
],
})
.on('success', ({ data: { Subnets: subnets } }) => {
const transformedSubnets = subnets.map(({ SubnetId: id }) => ({ id, name: id }));
resolve(transformedSubnets);
})
.on('error', error => {
reject(error);
})
.send();
});
export default () => {};
Loading
Loading
@@ -4,4 +4,12 @@ export const setRegion = ({ commit }, payload) => {
commit(types.SET_REGION, payload);
};
 
export const setVpc = ({ commit }, payload) => {
commit(types.SET_VPC, payload);
};
export const setSubnet = ({ commit }, payload) => {
commit(types.SET_SUBNET, payload);
};
export default () => {};
Loading
Loading
@@ -4,10 +4,10 @@ export default fetchItems => ({
requestItems: ({ commit }) => commit(types.REQUEST_ITEMS),
receiveItemsSuccess: ({ commit }, payload) => commit(types.RECEIVE_ITEMS_SUCCESS, payload),
receiveItemsError: ({ commit }, payload) => commit(types.RECEIVE_ITEMS_ERROR, payload),
fetchItems: ({ dispatch }) => {
fetchItems: ({ dispatch }, payload) => {
dispatch('requestItems');
 
return fetchItems()
return fetchItems(payload)
.then(items => dispatch('receiveItemsSuccess', { items }))
.catch(error => dispatch('receiveItemsError', { error }));
},
Loading
Loading
Loading
Loading
@@ -19,6 +19,14 @@ const createStore = () =>
namespaced: true,
...clusterDropdownStore(awsServices.fetchRegions),
},
vpcs: {
namespaced: true,
...clusterDropdownStore(awsServices.fetchVpcs),
},
subnets: {
namespaced: true,
...clusterDropdownStore(awsServices.fetchSubnets),
},
},
});
 
Loading
Loading
// eslint-disable-next-line import/prefer-default-export
export const SET_REGION = 'SET_REGION';
export const SET_VPC = 'SET_VPC';
export const SET_SUBNET = 'SET_SUBNET';
Loading
Loading
@@ -4,4 +4,10 @@ export default {
[types.SET_REGION](state, { region }) {
state.selectedRegion = region;
},
[types.SET_VPC](state, { vpc }) {
state.selectedVpc = vpc;
},
[types.SET_SUBNET](state, { subnet }) {
state.selectedSubnet = subnet;
},
};
Loading
Loading
@@ -91,7 +91,7 @@ module UploadsActions
 
upload_paths = uploader.upload_paths(params[:filename])
upload = Upload.find_by(model: model, uploader: uploader_class.to_s, path: upload_paths)
upload&.build_uploader
upload&.retrieve_uploader
end
# rubocop: enable CodeReuse/ActiveRecord
 
Loading
Loading
Loading
Loading
@@ -86,3 +86,5 @@ module Ci
end
end
end
Ci::PipelineSchedule.prepend_if_ee('EE::Ci::PipelineSchedule')
Loading
Loading
@@ -45,3 +45,5 @@ module Ci
end
end
end
Ci::Trigger.prepend_if_ee('EE::Ci::Trigger')
Loading
Loading
@@ -64,3 +64,5 @@ module Clusters
end
end
end
Clusters::Concerns::ApplicationCore.prepend_if_ee('EE::Clusters::Concerns::ApplicationCore')
Loading
Loading
@@ -72,8 +72,15 @@ class CommitCollection
end.compact]
 
# Replace the commits, keeping the same order
@commits = @commits.map do |c|
replacements.fetch(c.id, c)
@commits = @commits.map do |original_commit|
# Return the original instance: if it didn't need to be batchloaded, it was
# already enriched.
batch_loaded_commit = replacements.fetch(original_commit.id, original_commit)
# If batch loading the commit failed, fall back to the original commit.
# We need to explicitly check `.nil?` since otherwise a `BatchLoader` instance
# that looks like `nil` is returned.
batch_loaded_commit.nil? ? original_commit : batch_loaded_commit
end
 
self
Loading
Loading
Loading
Loading
@@ -15,7 +15,7 @@ class Upload < ApplicationRecord
scope :with_files_stored_remotely, -> { where(store: ObjectStorage::Store::REMOTE) }
 
before_save :calculate_checksum!, if: :foreground_checksummable?
after_commit :schedule_checksum, if: :checksummable?
after_commit :schedule_checksum, if: :needs_checksum?
 
# as the FileUploader is not mounted, the default CarrierWave ActiveRecord
# hooks are not executed and the file will not be deleted
Loading
Loading
@@ -53,20 +53,41 @@ class Upload < ApplicationRecord
 
def calculate_checksum!
self.checksum = nil
return unless checksummable?
return unless needs_checksum?
 
self.checksum = Digest::SHA256.file(absolute_path).hexdigest
end
 
# Initialize the associated Uploader class with current model
#
# @param [String] mounted_as
# @return [GitlabUploader] one of the subclasses, defined at the model's uploader attribute
def build_uploader(mounted_as = nil)
uploader_class.new(model, mounted_as || mount_point).tap do |uploader|
uploader.upload = self
end
end
# Initialize the associated Uploader class with current model and
# retrieve existing file from the store to a local cache
#
# @param [String] mounted_as
# @return [GitlabUploader] one of the subclasses, defined at the model's uploader attribute
def retrieve_uploader(mounted_as = nil)
build_uploader(mounted_as).tap do |uploader|
uploader.retrieve_from_store!(identifier)
end
end
 
# This checks for existence of the upload on storage
#
# @return [Boolean] whether upload exists on storage
def exist?
exist = File.exist?(absolute_path)
exist = if local?
File.exist?(absolute_path)
else
retrieve_uploader.exists?
end
 
# Help sysadmins find missing upload files
if persisted? && !exist
Loading
Loading
@@ -91,18 +112,24 @@ class Upload < ApplicationRecord
store == ObjectStorage::Store::LOCAL
end
 
# Returns whether generating checksum is needed
#
# This takes into account whether file exists, if any checksum exists
# or if the storage has checksum generation code implemented
#
# @return [Boolean] whether generating a checksum is needed
def needs_checksum?
checksum.nil? && local? && exist?
end
private
 
def delete_file!
build_uploader.remove!
end
def checksummable?
checksum.nil? && local? && exist?
retrieve_uploader.remove!
end
 
def foreground_checksummable?
checksummable? && size <= CHECKSUM_THRESHOLD
needs_checksum? && size <= CHECKSUM_THRESHOLD
end
 
def schedule_checksum
Loading
Loading
Loading
Loading
@@ -19,7 +19,7 @@ class AvatarUploader < GitlabUploader
end
 
def absolute_path
self.class.absolute_path(model.avatar.upload)
self.class.absolute_path(upload)
end
 
private
Loading
Loading
Loading
Loading
@@ -99,6 +99,17 @@ class GitlabUploader < CarrierWave::Uploader::Base
end
end
 
# Used to replace an existing upload with another +file+ without modifying stored metadata
# Use this method only to repair/replace an existing upload, or to upload to a Geo secondary node
#
# @param [CarrierWave::SanitizedFile] file that will replace existing upload
# @return CarrierWave::SanitizedFile
def replace_file_without_saving!(file)
raise ArgumentError, 'should be a CarrierWave::SanitizedFile' unless file.is_a? CarrierWave::SanitizedFile
storage.store!(file)
end
private
 
# Designed to be overridden by child uploaders that have a dynamic path
Loading
Loading
Loading
Loading
@@ -12,7 +12,7 @@ class ImportIssuesCsvWorker
@project = Project.find(project_id)
@upload = Upload.find(upload_id)
 
importer = Issues::ImportCsvService.new(@user, @project, @upload.build_uploader)
importer = Issues::ImportCsvService.new(@user, @project, @upload.retrieve_uploader)
importer.execute
 
@upload.destroy
Loading
Loading
Loading
Loading
@@ -22,7 +22,7 @@ module ObjectStorage
 
def build_uploader(subject, mount_point)
case subject
when Upload then subject.build_uploader(mount_point)
when Upload then subject.retrieve_uploader(mount_point)
else
subject.send(mount_point) # rubocop:disable GitlabSecurity/PublicSend
end
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment