Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
d5fd3f9c
Commit
d5fd3f9c
authored
Dec 02, 2021
by
Sheldon Led
Committed by
Brandon Labuschagne
Dec 02, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move namespace storage_counter to new usage_quotas folder
parent
6944a912
Changes
21
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
301 additions
and
304 deletions
+301
-304
ee/app/assets/javascripts/pages/groups/usage_quotas/index.js
ee/app/assets/javascripts/pages/groups/usage_quotas/index.js
+2
-2
ee/app/assets/javascripts/pages/profiles/usage_quotas/index.js
...p/assets/javascripts/pages/profiles/usage_quotas/index.js
+2
-2
ee/app/assets/javascripts/storage_counter/constants.js
ee/app/assets/javascripts/storage_counter/constants.js
+0
-15
ee/app/assets/javascripts/storage_counter/utils.js
ee/app/assets/javascripts/storage_counter/utils.js
+0
-144
ee/app/assets/javascripts/usage_quotas/storage/components/namespace_storage_app.vue
...usage_quotas/storage/components/namespace_storage_app.vue
+3
-3
ee/app/assets/javascripts/usage_quotas/storage/components/storage_inline_alert.vue
.../usage_quotas/storage/components/storage_inline_alert.vue
+0
-0
ee/app/assets/javascripts/usage_quotas/storage/components/temporary_storage_increase_modal.vue
...s/storage/components/temporary_storage_increase_modal.vue
+0
-0
ee/app/assets/javascripts/usage_quotas/storage/components/usage_statistics.vue
...ipts/usage_quotas/storage/components/usage_statistics.vue
+0
-0
ee/app/assets/javascripts/usage_quotas/storage/components/usage_statistics_card.vue
...usage_quotas/storage/components/usage_statistics_card.vue
+0
-0
ee/app/assets/javascripts/usage_quotas/storage/constants.js
ee/app/assets/javascripts/usage_quotas/storage/constants.js
+16
-0
ee/app/assets/javascripts/usage_quotas/storage/init_namespace_storage.js
...avascripts/usage_quotas/storage/init_namespace_storage.js
+3
-3
ee/app/assets/javascripts/usage_quotas/storage/queries/namespace_storage.query.graphql
...ge_quotas/storage/queries/namespace_storage.query.graphql
+1
-1
ee/app/assets/javascripts/usage_quotas/storage/utils.js
ee/app/assets/javascripts/usage_quotas/storage/utils.js
+143
-2
ee/spec/frontend/storage_counter/mock_data.js
ee/spec/frontend/storage_counter/mock_data.js
+0
-32
ee/spec/frontend/storage_counter/utils_spec.js
ee/spec/frontend/storage_counter/utils_spec.js
+0
-85
ee/spec/frontend/usage_quotas/storage/components/namespace_storage_app_spec.js
...e_quotas/storage/components/namespace_storage_app_spec.js
+9
-9
ee/spec/frontend/usage_quotas/storage/components/storage_inline_alert_spec.js
...ge_quotas/storage/components/storage_inline_alert_spec.js
+1
-1
ee/spec/frontend/usage_quotas/storage/components/temporary_storage_increase_modal_spec.js
...orage/components/temporary_storage_increase_modal_spec.js
+1
-1
ee/spec/frontend/usage_quotas/storage/components/usage_statistics_spec.js
.../usage_quotas/storage/components/usage_statistics_spec.js
+3
-3
ee/spec/frontend/usage_quotas/storage/mock_data.js
ee/spec/frontend/usage_quotas/storage/mock_data.js
+31
-0
ee/spec/frontend/usage_quotas/storage/utils_spec.js
ee/spec/frontend/usage_quotas/storage/utils_spec.js
+86
-1
No files found.
ee/app/assets/javascripts/pages/groups/usage_quotas/index.js
View file @
d5fd3f9c
import
SeatUsageApp
from
'
ee/seat_usage
'
;
import
storageCounter
from
'
ee/storage_counter
'
;
import
initNamespaceStorage
from
'
ee/usage_quotas/storage/init_namespace_storage
'
;
import
LinkedTabs
from
'
~/lib/utils/bootstrap_linked_tabs
'
;
import
initSearchSettings
from
'
~/search_settings
'
;
...
...
@@ -21,7 +21,7 @@ const initVueApps = () => {
}
if
(
document
.
querySelector
(
'
#js-storage-counter-app
'
))
{
storageCounter
();
initNamespaceStorage
();
}
};
...
...
ee/app/assets/javascripts/pages/profiles/usage_quotas/index.js
View file @
d5fd3f9c
import
ciMinutesUsage
from
'
ee/ci_minutes_usage
'
;
import
storageCounter
from
'
ee/storage_counter
'
;
import
initNamespaceStorage
from
'
ee/usage_quotas/storage/init_namespace_storage
'
;
import
LinkedTabs
from
'
~/lib/utils/bootstrap_linked_tabs
'
;
if
(
document
.
querySelector
(
'
#js-storage-counter-app
'
))
{
storageCounter
();
initNamespaceStorage
();
// eslint-disable-next-line no-new
new
LinkedTabs
({
...
...
ee/app/assets/javascripts/storage_counter/constants.js
deleted
100644 → 0
View file @
6944a912
export
const
NONE_THRESHOLD
=
'
none
'
;
export
const
INFO_THRESHOLD
=
'
info
'
;
export
const
WARNING_THRESHOLD
=
'
warning
'
;
export
const
ALERT_THRESHOLD
=
'
alert
'
;
export
const
ERROR_THRESHOLD
=
'
error
'
;
export
const
STORAGE_USAGE_THRESHOLDS
=
{
[
NONE_THRESHOLD
]:
0.0
,
[
INFO_THRESHOLD
]:
0.5
,
[
WARNING_THRESHOLD
]:
0.75
,
[
ALERT_THRESHOLD
]:
0.95
,
[
ERROR_THRESHOLD
]:
1.0
,
};
export
const
PROJECTS_PER_PAGE
=
20
;
ee/app/assets/javascripts/storage_counter/utils.js
deleted
100644 → 0
View file @
6944a912
import
{
numberToHumanSize
,
bytesToKiB
}
from
'
~/lib/utils/number_utils
'
;
import
{
getFormatter
,
SUPPORTED_FORMATS
}
from
'
~/lib/utils/unit_format
'
;
import
{
STORAGE_USAGE_THRESHOLDS
}
from
'
./constants
'
;
export
function
usageRatioToThresholdLevel
(
currentUsageRatio
)
{
let
currentLevel
=
Object
.
keys
(
STORAGE_USAGE_THRESHOLDS
)[
0
];
Object
.
keys
(
STORAGE_USAGE_THRESHOLDS
).
forEach
((
thresholdLevel
)
=>
{
if
(
currentUsageRatio
>=
STORAGE_USAGE_THRESHOLDS
[
thresholdLevel
])
currentLevel
=
thresholdLevel
;
});
return
currentLevel
;
}
/**
* Formats given bytes to formatted human readable size
*
* We want to display all units above bytes. Hence
* converting bytesToKiB before passing it to
* `getFormatter`
* @param {Number} size size in bytes
* @returns {String}
*/
export
const
formatUsageSize
=
(
size
)
=>
{
const
formatDecimalBytes
=
getFormatter
(
SUPPORTED_FORMATS
.
kibibytes
);
return
formatDecimalBytes
(
bytesToKiB
(
size
),
1
);
};
/**
* Parses each project to add additional purchased data
* equally so that locked projects can be unlocked.
*
* For example, if a group contains the below projects and
* project 2, 3 have exceeded the default 10.0 GB limit.
* 2 and 3 will remain locked until user purchases additional
* data.
*
* Project 1: 7.0GB
* Project 2: 13.0GB Locked
* Project 3: 12.0GB Locked
*
* If user purchases X GB, it will be equally available
* to all the locked projects for further use.
*
* @param {Object} data project
* @param {Number} purchasedStorageRemaining Remaining purchased data in bytes
* @returns {Object}
*/
export
const
calculateUsedAndRemStorage
=
(
project
,
purchasedStorageRemaining
)
=>
{
// We only consider repo size and lfs object size as of %13.5
const
totalCalculatedUsedStorage
=
project
.
statistics
.
repositorySize
+
project
.
statistics
.
lfsObjectsSize
;
// If a project size is above the default limit, then the remaining
// storage value will be calculated on top of the project size as
// opposed to the default limit.
// This
const
totalCalculatedStorageLimit
=
totalCalculatedUsedStorage
>
project
.
actualRepositorySizeLimit
?
totalCalculatedUsedStorage
+
purchasedStorageRemaining
:
project
.
actualRepositorySizeLimit
+
purchasedStorageRemaining
;
return
{
...
project
,
totalCalculatedUsedStorage
,
totalCalculatedStorageLimit
,
};
};
/**
* Parses projects coming in from GraphQL response
* and patches each project with purchased related
* data
*
* @param {Array} params.projects list of projects
* @param {Number} params.additionalPurchasedStorageSize Amt purchased in bytes
* @param {Number} params.totalRepositorySizeExcess Sum of excess amounts on all projects
* @returns {Array}
*/
export
const
parseProjects
=
({
projects
,
additionalPurchasedStorageSize
=
0
,
totalRepositorySizeExcess
=
0
,
})
=>
{
const
purchasedStorageRemaining
=
Math
.
max
(
0
,
additionalPurchasedStorageSize
-
totalRepositorySizeExcess
,
);
return
projects
.
nodes
.
map
((
project
)
=>
calculateUsedAndRemStorage
(
project
,
purchasedStorageRemaining
),
);
};
/**
* This method parses the results from `getStorageCounter`
* call.
*
* `rootStorageStatistics` will be sent as null until an
* event happens to trigger the storage count.
* For that reason we have to verify if `storageSize` is sent or
* if we should render N/A
*
* @param {Object} data graphql result
* @returns {Object}
*/
export
const
parseGetStorageResults
=
(
data
)
=>
{
const
{
namespace
:
{
projects
,
storageSizeLimit
,
totalRepositorySize
,
containsLockedProjects
,
totalRepositorySizeExcess
,
rootStorageStatistics
=
{},
actualRepositorySizeLimit
,
additionalPurchasedStorageSize
,
repositorySizeExcessProjectCount
,
},
}
=
data
||
{};
const
totalUsage
=
rootStorageStatistics
?.
storageSize
?
numberToHumanSize
(
rootStorageStatistics
.
storageSize
)
:
'
N/A
'
;
return
{
projects
:
{
data
:
parseProjects
({
projects
,
additionalPurchasedStorageSize
,
totalRepositorySizeExcess
,
}),
pageInfo
:
projects
.
pageInfo
,
},
additionalPurchasedStorageSize
,
actualRepositorySizeLimit
,
containsLockedProjects
,
repositorySizeExcessProjectCount
,
totalRepositorySize
,
totalRepositorySizeExcess
,
totalUsage
,
rootStorageStatistics
,
limit
:
storageSizeLimit
,
};
};
ee/app/assets/javascripts/
storage_counter/components/
app.vue
→
ee/app/assets/javascripts/
usage_quotas/storage/components/namespace_storage_
app.vue
View file @
d5fd3f9c
...
...
@@ -10,16 +10,16 @@ import {
import
{
parseBoolean
}
from
'
~/lib/utils/common_utils
'
;
import
UsageGraph
from
'
~/vue_shared/components/storage_counter/usage_graph.vue
'
;
import
glFeatureFlagsMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
import
ProjectList
from
'
ee/usage_quotas/storage/components/project_list.vue
'
;
import
{
PROJECTS_PER_PAGE
}
from
'
../constants
'
;
import
query
from
'
../queries/storage.query.graphql
'
;
import
query
from
'
../queries/
namespace_
storage.query.graphql
'
;
import
{
formatUsageSize
,
parseGetStorageResults
}
from
'
../utils
'
;
import
ProjectList
from
'
./project_list.vue
'
;
import
StorageInlineAlert
from
'
./storage_inline_alert.vue
'
;
import
TemporaryStorageIncreaseModal
from
'
./temporary_storage_increase_modal.vue
'
;
import
UsageStatistics
from
'
./usage_statistics.vue
'
;
export
default
{
name
:
'
StorageCounter
App
'
,
name
:
'
NamespaceStorage
App
'
,
components
:
{
GlLink
,
GlIcon
,
...
...
ee/app/assets/javascripts/
storage_counter
/components/storage_inline_alert.vue
→
ee/app/assets/javascripts/
usage_quotas/storage
/components/storage_inline_alert.vue
View file @
d5fd3f9c
File moved
ee/app/assets/javascripts/
storage_counter
/components/temporary_storage_increase_modal.vue
→
ee/app/assets/javascripts/
usage_quotas/storage
/components/temporary_storage_increase_modal.vue
View file @
d5fd3f9c
File moved
ee/app/assets/javascripts/
storage_counter
/components/usage_statistics.vue
→
ee/app/assets/javascripts/
usage_quotas/storage
/components/usage_statistics.vue
View file @
d5fd3f9c
File moved
ee/app/assets/javascripts/
storage_counter
/components/usage_statistics_card.vue
→
ee/app/assets/javascripts/
usage_quotas/storage
/components/usage_statistics_card.vue
View file @
d5fd3f9c
File moved
ee/app/assets/javascripts/usage_quotas/storage/constants.js
View file @
d5fd3f9c
...
...
@@ -60,3 +60,19 @@ export const PROJECT_TABLE_LABEL_STORAGE_TYPE = s__('UsageQuota|Storage type');
export
const
PROJECT_TABLE_LABEL_USAGE
=
s__
(
'
UsageQuota|Usage
'
);
export
const
SKELETON_LOADER_ROWS
=
5
;
export
const
NONE_THRESHOLD
=
'
none
'
;
export
const
INFO_THRESHOLD
=
'
info
'
;
export
const
WARNING_THRESHOLD
=
'
warning
'
;
export
const
ALERT_THRESHOLD
=
'
alert
'
;
export
const
ERROR_THRESHOLD
=
'
error
'
;
export
const
STORAGE_USAGE_THRESHOLDS
=
{
[
NONE_THRESHOLD
]:
0.0
,
[
INFO_THRESHOLD
]:
0.5
,
[
WARNING_THRESHOLD
]:
0.75
,
[
ALERT_THRESHOLD
]:
0.95
,
[
ERROR_THRESHOLD
]:
1.0
,
};
export
const
PROJECTS_PER_PAGE
=
20
;
ee/app/assets/javascripts/
storage_counter/index
.js
→
ee/app/assets/javascripts/
usage_quotas/storage/init_namespace_storage
.js
View file @
d5fd3f9c
import
Vue
from
'
vue
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
createDefaultClient
from
'
~/lib/graphql
'
;
import
App
from
'
./components/
app.vue
'
;
import
NamespaceStorageApp
from
'
./components/namespace_storage_
app.vue
'
;
Vue
.
use
(
VueApollo
);
...
...
@@ -21,8 +21,8 @@ export default () => {
return
new
Vue
({
el
,
apolloProvider
,
render
(
h
)
{
return
h
(
App
,
{
render
(
createElement
)
{
return
createElement
(
NamespaceStorage
App
,
{
props
:
{
namespacePath
,
helpPagePath
,
...
...
ee/app/assets/javascripts/
storage_counter/queries/
storage.query.graphql
→
ee/app/assets/javascripts/
usage_quotas/storage/queries/namespace_
storage.query.graphql
View file @
d5fd3f9c
#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
query
get
StorageCounter
(
query
get
NamespaceStorageStatistics
(
$fullPath
:
ID
!
$withExcessStorageData
:
Boolean
=
false
$searchTerm
:
String
=
""
...
...
ee/app/assets/javascripts/usage_quotas/storage/utils.js
View file @
d5fd3f9c
import
{
numberToHumanSize
}
from
'
~/lib/utils/number_utils
'
;
import
{
PROJECT_STORAGE_TYPES
}
from
'
./constants
'
;
import
{
numberToHumanSize
,
bytesToKiB
}
from
'
~/lib/utils/number_utils
'
;
import
{
getFormatter
,
SUPPORTED_FORMATS
}
from
'
~/lib/utils/unit_format
'
;
import
{
PROJECT_STORAGE_TYPES
,
STORAGE_USAGE_THRESHOLDS
}
from
'
./constants
'
;
export
function
usageRatioToThresholdLevel
(
currentUsageRatio
)
{
let
currentLevel
=
Object
.
keys
(
STORAGE_USAGE_THRESHOLDS
)[
0
];
Object
.
keys
(
STORAGE_USAGE_THRESHOLDS
).
forEach
((
thresholdLevel
)
=>
{
if
(
currentUsageRatio
>=
STORAGE_USAGE_THRESHOLDS
[
thresholdLevel
])
currentLevel
=
thresholdLevel
;
});
return
currentLevel
;
}
/**
* Formats given bytes to formatted human readable size
*
* We want to display all units above bytes. Hence
* converting bytesToKiB before passing it to
* `getFormatter`
* @param {Number} size size in bytes
* @returns {String}
*/
export
const
formatUsageSize
=
(
size
)
=>
{
const
formatDecimalBytes
=
getFormatter
(
SUPPORTED_FORMATS
.
kibibytes
);
return
formatDecimalBytes
(
bytesToKiB
(
size
),
1
);
};
/**
* Parses each project to add additional purchased data
* equally so that locked projects can be unlocked.
*
* For example, if a group contains the below projects and
* project 2, 3 have exceeded the default 10.0 GB limit.
* 2 and 3 will remain locked until user purchases additional
* data.
*
* Project 1: 7.0GB
* Project 2: 13.0GB Locked
* Project 3: 12.0GB Locked
*
* If user purchases X GB, it will be equally available
* to all the locked projects for further use.
*
* @param {Object} data project
* @param {Number} purchasedStorageRemaining Remaining purchased data in bytes
* @returns {Object}
*/
export
const
calculateUsedAndRemStorage
=
(
project
,
purchasedStorageRemaining
)
=>
{
// We only consider repo size and lfs object size as of %13.5
const
totalCalculatedUsedStorage
=
project
.
statistics
.
repositorySize
+
project
.
statistics
.
lfsObjectsSize
;
// If a project size is above the default limit, then the remaining
// storage value will be calculated on top of the project size as
// opposed to the default limit.
// This
const
totalCalculatedStorageLimit
=
totalCalculatedUsedStorage
>
project
.
actualRepositorySizeLimit
?
totalCalculatedUsedStorage
+
purchasedStorageRemaining
:
project
.
actualRepositorySizeLimit
+
purchasedStorageRemaining
;
return
{
...
project
,
totalCalculatedUsedStorage
,
totalCalculatedStorageLimit
,
};
};
/**
* Parses projects coming in from GraphQL response
* and patches each project with purchased related
* data
*
* @param {Array} params.projects list of projects
* @param {Number} params.additionalPurchasedStorageSize Amt purchased in bytes
* @param {Number} params.totalRepositorySizeExcess Sum of excess amounts on all projects
* @returns {Array}
*/
export
const
parseProjects
=
({
projects
,
additionalPurchasedStorageSize
=
0
,
totalRepositorySizeExcess
=
0
,
})
=>
{
const
purchasedStorageRemaining
=
Math
.
max
(
0
,
additionalPurchasedStorageSize
-
totalRepositorySizeExcess
,
);
return
projects
.
nodes
.
map
((
project
)
=>
calculateUsedAndRemStorage
(
project
,
purchasedStorageRemaining
),
);
};
/**
* This method parses the results from `getNamespaceStorageStatistics`
* call.
*
* `rootStorageStatistics` will be sent as null until an
* event happens to trigger the storage count.
* For that reason we have to verify if `storageSize` is sent or
* if we should render N/A
*
* @param {Object} data graphql result
* @returns {Object}
*/
export
const
parseGetStorageResults
=
(
data
)
=>
{
const
{
namespace
:
{
projects
,
storageSizeLimit
,
totalRepositorySize
,
containsLockedProjects
,
totalRepositorySizeExcess
,
rootStorageStatistics
=
{},
actualRepositorySizeLimit
,
additionalPurchasedStorageSize
,
repositorySizeExcessProjectCount
,
},
}
=
data
||
{};
const
totalUsage
=
rootStorageStatistics
?.
storageSize
?
numberToHumanSize
(
rootStorageStatistics
.
storageSize
)
:
'
N/A
'
;
return
{
projects
:
{
data
:
parseProjects
({
projects
,
additionalPurchasedStorageSize
,
totalRepositorySizeExcess
,
}),
pageInfo
:
projects
.
pageInfo
,
},
additionalPurchasedStorageSize
,
actualRepositorySizeLimit
,
containsLockedProjects
,
repositorySizeExcessProjectCount
,
totalRepositorySize
,
totalRepositorySizeExcess
,
totalUsage
,
rootStorageStatistics
,
limit
:
storageSizeLimit
,
};
};
export
const
getStorageTypesFromProjectStatistics
=
(
projectStatistics
,
helpLinks
=
{})
=>
PROJECT_STORAGE_TYPES
.
reduce
((
types
,
currentType
)
=>
{
...
...
ee/spec/frontend/storage_counter/mock_data.js
deleted
100644 → 0
View file @
6944a912
import
{
projects
}
from
'
ee_jest/usage_quotas/storage/mock_data
'
;
export
const
namespaceData
=
{
totalUsage
:
'
N/A
'
,
limit
:
10000000
,
projects
:
{
data
:
projects
},
};
export
const
withRootStorageStatistics
=
{
projects
,
limit
:
10000000
,
totalUsage
:
129334601
,
containsLockedProjects
:
true
,
repositorySizeExcessProjectCount
:
1
,
totalRepositorySizeExcess
:
2321
,
totalRepositorySize
:
1002321
,
additionalPurchasedStorageSize
:
321
,
actualRepositorySizeLimit
:
1002321
,
rootStorageStatistics
:
{
storageSize
:
129334601
,
repositorySize
:
46012030
,
lfsObjectsSize
:
4329334601203
,
buildArtifactsSize
:
1272375
,
packagesSize
:
123123120
,
wikiSize
:
1000
,
snippetsSize
:
10000
,
},
};
export
const
mockGetStorageCounterGraphQLResponse
=
{
nodes
:
projects
.
map
((
node
)
=>
node
),
};
ee/spec/frontend/storage_counter/utils_spec.js
deleted
100644 → 0
View file @
6944a912
import
{
usageRatioToThresholdLevel
,
formatUsageSize
,
parseProjects
,
calculateUsedAndRemStorage
,
}
from
'
ee/storage_counter/utils
'
;
import
{
projects
as
mockProjectsData
}
from
'
ee_jest/usage_quotas/storage/mock_data
'
;
import
{
mockGetStorageCounterGraphQLResponse
}
from
'
./mock_data
'
;
describe
(
'
UsageThreshold
'
,
()
=>
{
it
.
each
`
usageRatio | expectedLevel
${
0
}
|
${
'
none
'
}
${
0.4
}
|
${
'
none
'
}
${
0.5
}
|
${
'
info
'
}
${
0.9
}
|
${
'
warning
'
}
${
0.99
}
|
${
'
alert
'
}
${
1
}
|
${
'
error
'
}
${
1.5
}
|
${
'
error
'
}
`
(
'
returns $expectedLevel from $usageRatio
'
,
({
usageRatio
,
expectedLevel
})
=>
{
expect
(
usageRatioToThresholdLevel
(
usageRatio
)).
toBe
(
expectedLevel
);
});
});
describe
(
'
formatUsageSize
'
,
()
=>
{
it
.
each
`
input | expected
${
0
}
|
${
'
0.0KiB
'
}
${
999
}
|
${
'
1.0KiB
'
}
${
1000
}
|
${
'
1.0KiB
'
}
${
10240
}
|
${
'
10.0KiB
'
}
${
1024
*
10
**
5
}
|
${
'
97.7MiB
'
}
${
10
**
6
}
|
${
'
976.6KiB
'
}
${
1024
*
10
**
6
}
|
${
'
976.6MiB
'
}
${
10
**
8
}
|
${
'
95.4MiB
'
}
${
1024
*
10
**
8
}
|
${
'
95.4GiB
'
}
${
10
**
10
}
|
${
'
9.3GiB
'
}
${
10
**
12
}
|
${
'
931.3GiB
'
}
${
10
**
15
}
|
${
'
909.5TiB
'
}
`
(
'
returns $expected from $input
'
,
({
input
,
expected
})
=>
{
expect
(
formatUsageSize
(
input
)).
toBe
(
expected
);
});
});
describe
(
'
calculateUsedAndRemStorage
'
,
()
=>
{
it
.
each
`
description | project | purchasedStorageRemaining | totalCalculatedUsedStorage | totalCalculatedStorageLimit
${
'
project within limit and purchased 0
'
}
|
${
mockProjectsData
[
0
]}
|
${
0
}
|
${
41943
}
|
${
100000
}
${
'
project within limit and purchased 10000
'
}
|
${
mockProjectsData
[
0
]}
|
${
100000
}
|
${
41943
}
|
${
200000
}
${
'
project in warning state and purchased 0
'
}
|
${
mockProjectsData
[
1
]}
|
${
0
}
|
${
0
}
|
${
100000
}
${
'
project in warning state and purchased 10000
'
}
|
${
mockProjectsData
[
1
]}
|
${
100000
}
|
${
0
}
|
${
200000
}
${
'
project in error state and purchased 0
'
}
|
${
mockProjectsData
[
2
]}
|
${
0
}
|
${
419430
}
|
${
419430
}
${
'
project in error state and purchased 10000
'
}
|
${
mockProjectsData
[
2
]}
|
${
100000
}
|
${
419430
}
|
${
519430
}
`
(
'
returns used: $totalCalculatedUsedStorage and remaining: $totalCalculatedStorageLimit storage for $description
'
,
({
project
,
purchasedStorageRemaining
,
totalCalculatedUsedStorage
,
totalCalculatedStorageLimit
,
})
=>
{
const
result
=
calculateUsedAndRemStorage
(
project
,
purchasedStorageRemaining
);
expect
(
result
.
totalCalculatedUsedStorage
).
toBe
(
totalCalculatedUsedStorage
);
expect
(
result
.
totalCalculatedStorageLimit
).
toBe
(
totalCalculatedStorageLimit
);
},
);
});
describe
(
'
parseProjects
'
,
()
=>
{
it
(
'
ensures all projects have totalCalculatedUsedStorage and totalCalculatedStorageLimit
'
,
()
=>
{
const
projects
=
parseProjects
({
projects
:
mockGetStorageCounterGraphQLResponse
,
additionalPurchasedStorageSize
:
10000
,
totalRepositorySizeExcess
:
5000
,
});
projects
.
forEach
((
project
)
=>
{
expect
(
project
).
toMatchObject
({
totalCalculatedUsedStorage
:
expect
.
any
(
Number
),
totalCalculatedStorageLimit
:
expect
.
any
(
Number
),
});
});
});
});
ee/spec/frontend/
storage_counter/components/
app_spec.js
→
ee/spec/frontend/
usage_quotas/storage/components/namespace_storage_
app_spec.js
View file @
d5fd3f9c
import
{
mount
}
from
'
@vue/test-utils
'
;
import
StorageApp
from
'
ee/storage_counter/components/
app.vue
'
;
import
NamespaceStorageApp
from
'
ee/usage_quotas/storage/components/namespace_storage_
app.vue
'
;
import
CollapsibleProjectStorageDetail
from
'
ee/usage_quotas/storage/components/collapsible_project_storage_detail.vue
'
;
import
ProjectList
from
'
ee/usage_quotas/storage/components/project_list.vue
'
;
import
StorageInlineAlert
from
'
ee/
storage_counter
/components/storage_inline_alert.vue
'
;
import
TemporaryStorageIncreaseModal
from
'
ee/
storage_counter
/components/temporary_storage_increase_modal.vue
'
;
import
UsageStatistics
from
'
ee/
storage_counter
/components/usage_statistics.vue
'
;
import
{
formatUsageSize
}
from
'
ee/
storage_counter
/utils
'
;
import
StorageInlineAlert
from
'
ee/
usage_quotas/storage
/components/storage_inline_alert.vue
'
;
import
TemporaryStorageIncreaseModal
from
'
ee/
usage_quotas/storage
/components/temporary_storage_increase_modal.vue
'
;
import
UsageStatistics
from
'
ee/
usage_quotas/storage
/components/usage_statistics.vue
'
;
import
{
formatUsageSize
}
from
'
ee/
usage_quotas/storage
/utils
'
;
import
{
createMockDirective
,
getBinding
}
from
'
helpers/vue_mock_directive
'
;
import
UsageGraph
from
'
~/vue_shared/components/storage_counter/usage_graph.vue
'
;
import
{
namespaceData
,
withRootStorageStatistics
}
from
'
../mock_data
'
;
const
TEST_LIMIT
=
1000
;
describe
(
'
Storage counter a
pp
'
,
()
=>
{
describe
(
'
NamespaceStorageA
pp
'
,
()
=>
{
let
wrapper
;
const
findTotalUsage
=
()
=>
wrapper
.
find
(
"
[data-testid='total-usage']
"
);
...
...
@@ -40,7 +40,7 @@ describe('Storage counter app', () => {
},
};
wrapper
=
mount
(
StorageApp
,
{
wrapper
=
mount
(
Namespace
StorageApp
,
{
propsData
:
{
namespacePath
:
'
h5bp
'
,
helpPagePath
:
'
help
'
,
...
props
},
mocks
:
{
$apollo
},
directives
:
{
...
...
@@ -206,13 +206,13 @@ describe('Storage counter app', () => {
// Check for truthiness so we're assured we're not comparing two undefineds
expect
(
value
).
toBeTruthy
();
expect
(
value
).
toEqual
(
StorageApp
.
modalId
);
expect
(
value
).
toEqual
(
Namespace
StorageApp
.
modalId
);
});
it
(
'
renders modal
'
,
()
=>
{
expect
(
wrapper
.
find
(
TemporaryStorageIncreaseModal
).
props
()).
toEqual
({
limit
:
formatUsageSize
(
TEST_LIMIT
),
modalId
:
StorageApp
.
modalId
,
modalId
:
Namespace
StorageApp
.
modalId
,
});
});
});
...
...
ee/spec/frontend/
storage_counter
/components/storage_inline_alert_spec.js
→
ee/spec/frontend/
usage_quotas/storage
/components/storage_inline_alert_spec.js
View file @
d5fd3f9c
import
{
GlAlert
}
from
'
@gitlab/ui
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
StorageInlineAlert
from
'
ee/
storage_counter
/components/storage_inline_alert.vue
'
;
import
StorageInlineAlert
from
'
ee/
usage_quotas/storage
/components/storage_inline_alert.vue
'
;
const
GB_IN_BYTES
=
1
_074_000_000
;
const
THIRTEEN_GB_IN_BYTES
=
13
*
GB_IN_BYTES
;
...
...
ee/spec/frontend/
storage_counter
/components/temporary_storage_increase_modal_spec.js
→
ee/spec/frontend/
usage_quotas/storage
/components/temporary_storage_increase_modal_spec.js
View file @
d5fd3f9c
import
{
GlModal
}
from
'
@gitlab/ui
'
;
import
{
mount
,
shallowMount
}
from
'
@vue/test-utils
'
;
import
TemporaryStorageIncreaseModal
from
'
ee/
storage_counter
/components/temporary_storage_increase_modal.vue
'
;
import
TemporaryStorageIncreaseModal
from
'
ee/
usage_quotas/storage
/components/temporary_storage_increase_modal.vue
'
;
const
TEST_LIMIT
=
'
8 bytes
'
;
const
TEST_MODAL_ID
=
'
test-modal-id
'
;
...
...
ee/spec/frontend/
storage_counter
/components/usage_statistics_spec.js
→
ee/spec/frontend/
usage_quotas/storage
/components/usage_statistics_spec.js
View file @
d5fd3f9c
import
{
GlButton
,
GlLink
,
GlSprintf
}
from
'
@gitlab/ui
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
UsageStatistics
from
'
ee/
storage_counter
/components/usage_statistics.vue
'
;
import
UsageStatisticsCard
from
'
ee/
storage_counter
/components/usage_statistics_card.vue
'
;
import
UsageStatistics
from
'
ee/
usage_quotas/storage
/components/usage_statistics.vue
'
;
import
UsageStatisticsCard
from
'
ee/
usage_quotas/storage
/components/usage_statistics_card.vue
'
;
import
{
withRootStorageStatistics
}
from
'
../mock_data
'
;
describe
(
'
Usage
Statistics component
'
,
()
=>
{
describe
(
'
Usage
Statistics
'
,
()
=>
{
let
wrapper
;
const
createComponent
=
({
props
=
{},
newRouteStoragePurchase
=
false
}
=
{})
=>
{
...
...
ee/spec/frontend/usage_quotas/storage/mock_data.js
View file @
d5fd3f9c
...
...
@@ -152,3 +152,34 @@ export const defaultProjectProvideValues = {
projectPath
:
'
/project-path
'
,
helpLinks
:
projectHelpLinks
,
};
export
const
namespaceData
=
{
totalUsage
:
'
N/A
'
,
limit
:
10000000
,
projects
:
{
data
:
projects
},
};
export
const
withRootStorageStatistics
=
{
projects
,
limit
:
10000000
,
totalUsage
:
129334601
,
containsLockedProjects
:
true
,
repositorySizeExcessProjectCount
:
1
,
totalRepositorySizeExcess
:
2321
,
totalRepositorySize
:
1002321
,
additionalPurchasedStorageSize
:
321
,
actualRepositorySizeLimit
:
1002321
,
rootStorageStatistics
:
{
storageSize
:
129334601
,
repositorySize
:
46012030
,
lfsObjectsSize
:
4329334601203
,
buildArtifactsSize
:
1272375
,
packagesSize
:
123123120
,
wikiSize
:
1000
,
snippetsSize
:
10000
,
},
};
export
const
mockGetNamespaceStorageStatisticsGraphQLResponse
=
{
nodes
:
projects
.
map
((
node
)
=>
node
),
};
ee/spec/frontend/usage_quotas/storage/utils_spec.js
View file @
d5fd3f9c
import
{
parseGetProjectStorageResults
}
from
'
ee/usage_quotas/storage/utils
'
;
import
{
usageRatioToThresholdLevel
,
formatUsageSize
,
parseProjects
,
calculateUsedAndRemStorage
,
parseGetProjectStorageResults
,
}
from
'
ee/usage_quotas/storage/utils
'
;
import
{
projectData
,
projects
as
mockProjectsData
,
mockGetProjectStorageStatisticsGraphQLResponse
,
mockGetNamespaceStorageStatisticsGraphQLResponse
,
defaultProjectProvideValues
,
}
from
'
./mock_data
'
;
...
...
@@ -35,3 +43,80 @@ describe('parseGetProjectStorageResults', () => {
);
});
});
describe
(
'
UsageThreshold
'
,
()
=>
{
it
.
each
`
usageRatio | expectedLevel
${
0
}
|
${
'
none
'
}
${
0.4
}
|
${
'
none
'
}
${
0.5
}
|
${
'
info
'
}
${
0.9
}
|
${
'
warning
'
}
${
0.99
}
|
${
'
alert
'
}
${
1
}
|
${
'
error
'
}
${
1.5
}
|
${
'
error
'
}
`
(
'
returns $expectedLevel from $usageRatio
'
,
({
usageRatio
,
expectedLevel
})
=>
{
expect
(
usageRatioToThresholdLevel
(
usageRatio
)).
toBe
(
expectedLevel
);
});
});
describe
(
'
formatUsageSize
'
,
()
=>
{
it
.
each
`
input | expected
${
0
}
|
${
'
0.0KiB
'
}
${
999
}
|
${
'
1.0KiB
'
}
${
1000
}
|
${
'
1.0KiB
'
}
${
10240
}
|
${
'
10.0KiB
'
}
${
1024
*
10
**
5
}
|
${
'
97.7MiB
'
}
${
10
**
6
}
|
${
'
976.6KiB
'
}
${
1024
*
10
**
6
}
|
${
'
976.6MiB
'
}
${
10
**
8
}
|
${
'
95.4MiB
'
}
${
1024
*
10
**
8
}
|
${
'
95.4GiB
'
}
${
10
**
10
}
|
${
'
9.3GiB
'
}
${
10
**
12
}
|
${
'
931.3GiB
'
}
${
10
**
15
}
|
${
'
909.5TiB
'
}
`
(
'
returns $expected from $input
'
,
({
input
,
expected
})
=>
{
expect
(
formatUsageSize
(
input
)).
toBe
(
expected
);
});
});
describe
(
'
calculateUsedAndRemStorage
'
,
()
=>
{
it
.
each
`
description | project | purchasedStorageRemaining | totalCalculatedUsedStorage | totalCalculatedStorageLimit
${
'
project within limit and purchased 0
'
}
|
${
mockProjectsData
[
0
]}
|
${
0
}
|
${
41943
}
|
${
100000
}
${
'
project within limit and purchased 10000
'
}
|
${
mockProjectsData
[
0
]}
|
${
100000
}
|
${
41943
}
|
${
200000
}
${
'
project in warning state and purchased 0
'
}
|
${
mockProjectsData
[
1
]}
|
${
0
}
|
${
0
}
|
${
100000
}
${
'
project in warning state and purchased 10000
'
}
|
${
mockProjectsData
[
1
]}
|
${
100000
}
|
${
0
}
|
${
200000
}
${
'
project in error state and purchased 0
'
}
|
${
mockProjectsData
[
2
]}
|
${
0
}
|
${
419430
}
|
${
419430
}
${
'
project in error state and purchased 10000
'
}
|
${
mockProjectsData
[
2
]}
|
${
100000
}
|
${
419430
}
|
${
519430
}
`
(
'
returns used: $totalCalculatedUsedStorage and remaining: $totalCalculatedStorageLimit storage for $description
'
,
({
project
,
purchasedStorageRemaining
,
totalCalculatedUsedStorage
,
totalCalculatedStorageLimit
,
})
=>
{
const
result
=
calculateUsedAndRemStorage
(
project
,
purchasedStorageRemaining
);
expect
(
result
.
totalCalculatedUsedStorage
).
toBe
(
totalCalculatedUsedStorage
);
expect
(
result
.
totalCalculatedStorageLimit
).
toBe
(
totalCalculatedStorageLimit
);
},
);
});
describe
(
'
parseProjects
'
,
()
=>
{
it
(
'
ensures all projects have totalCalculatedUsedStorage and totalCalculatedStorageLimit
'
,
()
=>
{
const
projects
=
parseProjects
({
projects
:
mockGetNamespaceStorageStatisticsGraphQLResponse
,
additionalPurchasedStorageSize
:
10000
,
totalRepositorySizeExcess
:
5000
,
});
projects
.
forEach
((
project
)
=>
{
expect
(
project
).
toMatchObject
({
totalCalculatedUsedStorage
:
expect
.
any
(
Number
),
totalCalculatedStorageLimit
:
expect
.
any
(
Number
),
});
});
});
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment