mirror of
https://github.com/quay/quay.git
synced 2025-07-30 07:43:13 +03:00
marketplace: add support for quantity from subscriptions api (PROJQUAY-6551) (#2633)
* Adds handling for when a subscription returned from the subscription watch api has a quantity greater than 1. Number of private repos should be correctly calculated using the quantity. * Updates ui so that subscriptions can only be added to an org as a group, i.e. a subscription with quantity = 2 cannot be split across organizations.
This commit is contained in:
@ -2001,6 +2001,7 @@ class OrganizationRhSkus(BaseModel):
|
|||||||
subscription_id = IntegerField(index=True, unique=True)
|
subscription_id = IntegerField(index=True, unique=True)
|
||||||
user_id = ForeignKeyField(User, backref="org_bound_subscription")
|
user_id = ForeignKeyField(User, backref="org_bound_subscription")
|
||||||
org_id = ForeignKeyField(User, backref="subscription")
|
org_id = ForeignKeyField(User, backref="subscription")
|
||||||
|
quantity = IntegerField(index=True, null=True)
|
||||||
|
|
||||||
indexes = (
|
indexes = (
|
||||||
(("subscription_id", "org_id"), True),
|
(("subscription_id", "org_id"), True),
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
"""add quantity field to orgRhSkus
|
||||||
|
|
||||||
|
Revision ID: 41d15c93c299
|
||||||
|
Revises: 3f8e3657bb67
|
||||||
|
Create Date: 2024-01-24 11:19:19.095256
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = "41d15c93c299"
|
||||||
|
down_revision = "3f8e3657bb67"
|
||||||
|
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade(op, tables, tester):
|
||||||
|
op.add_column("organizationrhskus", sa.Column("quantity", sa.Integer(), nullable=True))
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade(op, tables, tester):
|
||||||
|
op.drop_column("organizationrhskus", "quantity")
|
@ -3,7 +3,7 @@ import logging
|
|||||||
import peewee
|
import peewee
|
||||||
|
|
||||||
from data import model
|
from data import model
|
||||||
from data.database import OrganizationRhSkus
|
from data.database import OrganizationRhSkus, db_transaction
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -16,10 +16,10 @@ def get_org_subscriptions(org_id):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def bind_subscription_to_org(subscription_id, org_id, user_id):
|
def bind_subscription_to_org(subscription_id, org_id, user_id, quantity=1):
|
||||||
try:
|
try:
|
||||||
return OrganizationRhSkus.create(
|
return OrganizationRhSkus.create(
|
||||||
subscription_id=subscription_id, org_id=org_id, user_id=user_id
|
subscription_id=subscription_id, org_id=org_id, user_id=user_id, quantity=quantity
|
||||||
)
|
)
|
||||||
except model.DataModelException as ex:
|
except model.DataModelException as ex:
|
||||||
logger.error("Problem binding subscription to org %s: %s", org_id, ex)
|
logger.error("Problem binding subscription to org %s: %s", org_id, ex)
|
||||||
|
@ -53,9 +53,11 @@ def check_internal_api_for_subscription(namespace_user):
|
|||||||
query = organization_skus.get_org_subscriptions(namespace_user.id)
|
query = organization_skus.get_org_subscriptions(namespace_user.id)
|
||||||
org_subscriptions = list(query.dicts()) if query is not None else []
|
org_subscriptions = list(query.dicts()) if query is not None else []
|
||||||
for subscription in org_subscriptions:
|
for subscription in org_subscriptions:
|
||||||
|
quantity = 1 if subscription.get("quantity") is None else subscription["quantity"]
|
||||||
subscription_id = subscription["subscription_id"]
|
subscription_id = subscription["subscription_id"]
|
||||||
sku = marketplace_subscriptions.get_subscription_sku(subscription_id)
|
sku = marketplace_subscriptions.get_subscription_sku(subscription_id)
|
||||||
plans.append(get_plan_using_rh_sku(sku))
|
for x in range(quantity):
|
||||||
|
plans.append(get_plan_using_rh_sku(sku))
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
user_account_number = marketplace_users.get_account_number(namespace_user)
|
user_account_number = marketplace_users.get_account_number(namespace_user)
|
||||||
@ -960,6 +962,8 @@ class OrganizationRhSku(ApiResource):
|
|||||||
)
|
)
|
||||||
subscription["sku"] = subscription_sku
|
subscription["sku"] = subscription_sku
|
||||||
subscription["metadata"] = get_plan_using_rh_sku(subscription_sku)
|
subscription["metadata"] = get_plan_using_rh_sku(subscription_sku)
|
||||||
|
if subscription.get("quantity") is None:
|
||||||
|
subscription["quantity"] = 1
|
||||||
return subscriptions
|
return subscriptions
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
@ -989,9 +993,17 @@ class OrganizationRhSku(ApiResource):
|
|||||||
|
|
||||||
user_subscription_ids = [int(subscription["id"]) for subscription in subscriptions]
|
user_subscription_ids = [int(subscription["id"]) for subscription in subscriptions]
|
||||||
if int(subscription_id) in user_subscription_ids:
|
if int(subscription_id) in user_subscription_ids:
|
||||||
|
quantity = 1
|
||||||
|
for subscription in subscriptions:
|
||||||
|
if subscription["id"] == subscription_id:
|
||||||
|
quantity = subscription["quantity"]
|
||||||
|
break
|
||||||
try:
|
try:
|
||||||
model.organization_skus.bind_subscription_to_org(
|
model.organization_skus.bind_subscription_to_org(
|
||||||
user_id=user.id, subscription_id=subscription_id, org_id=organization.id
|
user_id=user.id,
|
||||||
|
subscription_id=subscription_id,
|
||||||
|
org_id=organization.id,
|
||||||
|
quantity=quantity,
|
||||||
)
|
)
|
||||||
except model.OrgSubscriptionBindingAlreadyExists:
|
except model.OrgSubscriptionBindingAlreadyExists:
|
||||||
abort(400, message="subscription is already bound to an org")
|
abort(400, message="subscription is already bound to an org")
|
||||||
|
@ -384,7 +384,11 @@ class OrgPrivateRepositories(ApiResource):
|
|||||||
)
|
)
|
||||||
equivalent_stripe_plan = get_plan_using_rh_sku(subscription_sku)
|
equivalent_stripe_plan = get_plan_using_rh_sku(subscription_sku)
|
||||||
if equivalent_stripe_plan:
|
if equivalent_stripe_plan:
|
||||||
repos_allowed += equivalent_stripe_plan["privateRepos"]
|
if subscription.get("quantity") is None:
|
||||||
|
quantity = 1
|
||||||
|
else:
|
||||||
|
quantity = subscription["quantity"]
|
||||||
|
repos_allowed += quantity * equivalent_stripe_plan["privateRepos"]
|
||||||
|
|
||||||
data["privateAllowed"] = private_repos < repos_allowed
|
data["privateAllowed"] = private_repos < repos_allowed
|
||||||
|
|
||||||
|
@ -2,40 +2,33 @@
|
|||||||
<span><h3>Monthly Subscriptions From Red Hat Customer Portal</h3></span>
|
<span><h3>Monthly Subscriptions From Red Hat Customer Portal</h3></span>
|
||||||
<div class="cor-loader-inline" ng-show="marketplaceLoading"></div>
|
<div class="cor-loader-inline" ng-show="marketplaceLoading"></div>
|
||||||
<span ng-show="!organization && !marketplaceLoading">
|
<span ng-show="!organization && !marketplaceLoading">
|
||||||
<div ng-repeat="(sku, subscriptions) in userMarketplaceSubscriptions">
|
<div ng-repeat="subscription in userMarketplaceSubscriptions">
|
||||||
{{subscriptions.length}}x {{ sku }}
|
{{subscription.quantity}}x {{ subscription.sku }}
|
||||||
|
{{subscription.assigned_to_org ? "attached to org " + subscription.assigned_to_org : ""}}
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<table ng-show="organization && !marketplaceLoading">
|
<table ng-show="organization && !marketplaceLoading">
|
||||||
<tr class="indented-row" ng-repeat="(sku, subscriptions) in orgMarketplaceSubscriptions">
|
<tr class="indented-row" ng-repeat="subscription in orgMarketplaceSubscriptions">
|
||||||
<td>
|
<td>
|
||||||
{{ subscriptions.length }} x {{ sku }} attached to this org
|
{{ subscription.quantity }}x {{ subscription.sku }} attached to this org
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="indented-row">
|
<tr class="indented-row">
|
||||||
<td style="padding: 10px">
|
<td style="padding: 10px">
|
||||||
<select class="form-control" ng-model="subscriptionBinding">
|
<select class="form-control" ng-model="subscriptionBinding">
|
||||||
<option ng-repeat="(sku, subscriptions) in availableSubscriptions" value="{{ subscriptions }}">
|
<option ng-repeat="subscription in availableSubscriptions" value="{{ subscription }}">
|
||||||
{{subscriptions.length}} x {{sku}}
|
{{subscription.quantity}}x {{subscription.sku}}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<input class="form-control" type="number" min="1" max="{{subscriptions.length}}" ng-model="numSubscriptions" placeholder="Number of subscriptions">
|
<a class="btn btn-primary" ng-click="bindSku(subscriptionBinding)">Attach subscriptions</a>
|
||||||
<a class="btn btn-primary" ng-click="bindSku(subscriptionBinding, numSubscriptions)">Attach subscriptions</a>
|
|
||||||
</td>
|
</td>
|
||||||
<td style="padding: 10px">
|
<td style="padding: 10px">
|
||||||
<select class="form-control" ng-model="subscriptionRemovals">
|
<select class="form-control" ng-model="subscriptionRemovals">
|
||||||
<option ng-repeat="(sku, orgSubscriptions) in orgMarketplaceSubscriptions" value="{{orgSubscriptions}}">
|
<option ng-repeat="orgSubscription in orgMarketplaceSubscriptions" value="{{orgSubscription}}">
|
||||||
{{sku}}
|
{{orgSubscription.quantity}}x {{orgSubscription.sku}}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<input class="form-control"
|
|
||||||
type="number"
|
|
||||||
min="1"
|
|
||||||
max="{{JSON.parse(subscriptions).length}}"
|
|
||||||
ng-model="numRemovals"
|
|
||||||
placeholder="Number of subscriptions"
|
|
||||||
>
|
|
||||||
<a class="btn btn-default" ng-click="batchRemoveSku(subscriptionRemovals, numRemovals)">
|
<a class="btn btn-default" ng-click="batchRemoveSku(subscriptionRemovals, numRemovals)">
|
||||||
Remove subscriptions
|
Remove subscriptions
|
||||||
</a>
|
</a>
|
||||||
|
@ -50,7 +50,10 @@ angular.module('quay').directive('billingManagementPanel', function () {
|
|||||||
if ($scope.organization) {
|
if ($scope.organization) {
|
||||||
PlanService.listOrgMarketplaceSubscriptions($scope.organization.name, function(subscriptions){
|
PlanService.listOrgMarketplaceSubscriptions($scope.organization.name, function(subscriptions){
|
||||||
for (var i = 0; i < subscriptions.length; i++) {
|
for (var i = 0; i < subscriptions.length; i++) {
|
||||||
total += subscriptions[i]["metadata"]["privateRepos"];
|
total += (
|
||||||
|
subscriptions[i]["quantity"] *
|
||||||
|
subscriptions[i]["metadata"]["privateRepos"]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
$scope.currentMarketplace = total;
|
$scope.currentMarketplace = total;
|
||||||
})
|
})
|
||||||
@ -58,7 +61,10 @@ angular.module('quay').directive('billingManagementPanel', function () {
|
|||||||
PlanService.listUserMarketplaceSubscriptions(function(subscriptions){
|
PlanService.listUserMarketplaceSubscriptions(function(subscriptions){
|
||||||
for (var i = 0; i < subscriptions.length; i++) {
|
for (var i = 0; i < subscriptions.length; i++) {
|
||||||
if(subscriptions[i]["assigned_to_org"] === null) {
|
if(subscriptions[i]["assigned_to_org"] === null) {
|
||||||
total += subscriptions[i]["metadata"]["privateRepos"];
|
total += (
|
||||||
|
subscriptions[i]["quantity"] *
|
||||||
|
subscriptions[i]["metadata"]["privateRepos"]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$scope.currentMarketplace = total;
|
$scope.currentMarketplace = total;
|
||||||
|
@ -8,9 +8,9 @@ angular.module('quay').directive('orgBinding', function() {
|
|||||||
'organization': '=organization',
|
'organization': '=organization',
|
||||||
},
|
},
|
||||||
controller: function($scope, $timeout, PlanService, ApiService) {
|
controller: function($scope, $timeout, PlanService, ApiService) {
|
||||||
$scope.userMarketplaceSubscriptions = {};
|
$scope.userMarketplaceSubscriptions = [];
|
||||||
$scope.orgMarketplaceSubscriptions = {};
|
$scope.orgMarketplaceSubscriptions = [];
|
||||||
$scope.availableSubscriptions = {};
|
$scope.availableSubscriptions = [];
|
||||||
$scope.marketplaceLoading = true;
|
$scope.marketplaceLoading = true;
|
||||||
$scope.bindOrgSuccess = false;
|
$scope.bindOrgSuccess = false;
|
||||||
$scope.removeSkuSuccess = false;
|
$scope.removeSkuSuccess = false;
|
||||||
@ -34,9 +34,12 @@ angular.module('quay').directive('orgBinding', function() {
|
|||||||
if ($scope.organization) {
|
if ($scope.organization) {
|
||||||
PlanService.listOrgMarketplaceSubscriptions($scope.organization, function(marketplaceSubscriptions){
|
PlanService.listOrgMarketplaceSubscriptions($scope.organization, function(marketplaceSubscriptions){
|
||||||
// group the list of subscriptions by their sku field
|
// group the list of subscriptions by their sku field
|
||||||
$scope.orgMarketplaceSubscriptions = groupSubscriptionsBySku(marketplaceSubscriptions);
|
$scope.orgMarketplaceSubscriptions = marketplaceSubscriptions;
|
||||||
for (var i = 0; i < marketplaceSubscriptions.length; i++) {
|
for (var i = 0; i < marketplaceSubscriptions.length; i++) {
|
||||||
total += marketplaceSubscriptions[i]["metadata"]["privateRepos"];
|
total += (
|
||||||
|
marketplaceSubscriptions[i]["quantity"] *
|
||||||
|
marketplaceSubscriptions[i]["metadata"]["privateRepos"]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
$scope.marketplaceTotal = total;
|
$scope.marketplaceTotal = total;
|
||||||
});
|
});
|
||||||
@ -48,12 +51,15 @@ angular.module('quay').directive('orgBinding', function() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let notBound = [];
|
let notBound = [];
|
||||||
$scope.userMarketplaceSubscriptions = groupSubscriptionsBySku(marketplaceSubscriptions);
|
$scope.userMarketplaceSubscriptions = marketplaceSubscriptions;
|
||||||
|
|
||||||
for (var i = 0; i < marketplaceSubscriptions.length; i++) {
|
for (var i = 0; i < marketplaceSubscriptions.length; i++) {
|
||||||
if (marketplaceSubscriptions[i]["assigned_to_org"] === null) {
|
if (marketplaceSubscriptions[i]["assigned_to_org"] === null) {
|
||||||
if(!($scope.organization)){
|
if(!($scope.organization)){
|
||||||
total += marketplaceSubscriptions[i]["metadata"]["privateRepos"];
|
total += (
|
||||||
|
marketplaceSubscriptions[i]["quantity"] *
|
||||||
|
marketplaceSubscriptions[i]["metadata"]["privateRepos"]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
notBound.push(marketplaceSubscriptions[i]);
|
notBound.push(marketplaceSubscriptions[i]);
|
||||||
}
|
}
|
||||||
@ -61,7 +67,7 @@ angular.module('quay').directive('orgBinding', function() {
|
|||||||
if(!($scope.organization)){
|
if(!($scope.organization)){
|
||||||
$scope.marketplaceTotal = total;
|
$scope.marketplaceTotal = total;
|
||||||
}
|
}
|
||||||
$scope.availableSubscriptions = groupSubscriptionsBySku(notBound);
|
$scope.availableSubscriptions = notBound;
|
||||||
$scope.marketplaceLoading = false;
|
$scope.marketplaceLoading = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -71,21 +77,14 @@ angular.module('quay').directive('orgBinding', function() {
|
|||||||
loadSubscriptions();
|
loadSubscriptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.bindSku = function(subscriptions, numSubscriptions) {
|
$scope.bindSku = function(subscriptionToBind) {
|
||||||
let subscriptionArr = JSON.parse(subscriptions);
|
let subscription = JSON.parse(subscriptionToBind);
|
||||||
if(numSubscriptions > subscriptionArr.length){
|
|
||||||
displayError("number of subscriptions exceeds total amount");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$scope.marketplaceLoading = true;
|
$scope.marketplaceLoading = true;
|
||||||
const requestData = {};
|
const requestData = {};
|
||||||
requestData["subscriptions"] = [];
|
requestData["subscriptions"] = [];
|
||||||
for(var i = 0; i < numSubscriptions; ++i) {
|
requestData["subscriptions"].push({
|
||||||
var subscriptionObject = {};
|
"subscription_id": subscription["id"],
|
||||||
var subscriptionId = subscriptionArr[i].id;
|
});
|
||||||
subscriptionObject.subscription_id = subscriptionId;
|
|
||||||
requestData["subscriptions"].push(subscriptionObject);
|
|
||||||
}
|
|
||||||
PlanService.bindSkuToOrg(requestData, $scope.organization, function(resp){
|
PlanService.bindSkuToOrg(requestData, $scope.organization, function(resp){
|
||||||
if (resp === "Okay"){
|
if (resp === "Okay"){
|
||||||
bindSkuSuccessMessage();
|
bindSkuSuccessMessage();
|
||||||
@ -96,16 +95,11 @@ angular.module('quay').directive('orgBinding', function() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.batchRemoveSku = function(removals, numRemovals) {
|
$scope.batchRemoveSku = function(subscriptionToRemove) {
|
||||||
let removalArr = JSON.parse(removals);
|
let subscription = JSON.parse(subscriptionToRemove);
|
||||||
const requestData = {};
|
const requestData = {};
|
||||||
requestData["subscriptions"] = [];
|
requestData["subscriptions"] = [];
|
||||||
for(var i = 0; i < numRemovals; ++i){
|
requestData["subscriptions"].push({"subscription_id": subscription["subscription_id"]});
|
||||||
var subscriptionObject = {};
|
|
||||||
var subscriptionId = removalArr[i].subscription_id;
|
|
||||||
subscriptionObject.subscription_id = subscriptionId;
|
|
||||||
requestData["subscriptions"].push(subscriptionObject);
|
|
||||||
}
|
|
||||||
PlanService.batchRemoveSku(requestData, $scope.organization, function(resp){
|
PlanService.batchRemoveSku(requestData, $scope.organization, function(resp){
|
||||||
if (resp == "") {
|
if (resp == "") {
|
||||||
removeSkuSuccessMessage();
|
removeSkuSuccessMessage();
|
||||||
|
@ -42,6 +42,7 @@ from endpoints.api.billing import (
|
|||||||
UserCard,
|
UserCard,
|
||||||
UserPlan,
|
UserPlan,
|
||||||
UserSkuList,
|
UserSkuList,
|
||||||
|
check_internal_api_for_subscription,
|
||||||
)
|
)
|
||||||
from endpoints.api.build import (
|
from endpoints.api.build import (
|
||||||
RepositoryBuildList,
|
RepositoryBuildList,
|
||||||
@ -5078,7 +5079,7 @@ class TestOrganizationRhSku(ApiTestCase):
|
|||||||
self.postResponse(
|
self.postResponse(
|
||||||
resource_name=OrganizationRhSku,
|
resource_name=OrganizationRhSku,
|
||||||
params=dict(orgname=SUBSCRIPTION_ORG),
|
params=dict(orgname=SUBSCRIPTION_ORG),
|
||||||
data={"subscriptions": [{"subscription_id": 12345678}]},
|
data={"subscriptions": [{"subscription_id": 12345678, "quantity": 2}]},
|
||||||
expected_code=201,
|
expected_code=201,
|
||||||
)
|
)
|
||||||
json = self.getJsonResponse(
|
json = self.getJsonResponse(
|
||||||
@ -5164,6 +5165,19 @@ class TestOrganizationRhSku(ApiTestCase):
|
|||||||
)
|
)
|
||||||
self.assertEqual(len(json), 0)
|
self.assertEqual(len(json), 0)
|
||||||
|
|
||||||
|
def test_none_quantity(self):
|
||||||
|
self.login(SUBSCRIPTION_USER)
|
||||||
|
user = model.user.get_user(SUBSCRIPTION_USER)
|
||||||
|
org = model.organization.get_organization(SUBSCRIPTION_ORG)
|
||||||
|
model.organization_skus.bind_subscription_to_org(12345678, org.id, user.id, None)
|
||||||
|
json = self.getJsonResponse(
|
||||||
|
resource_name=OrganizationRhSku, params=dict(orgname=SUBSCRIPTION_ORG)
|
||||||
|
)
|
||||||
|
self.assertEqual(json[0]["quantity"], 1)
|
||||||
|
|
||||||
|
plans = check_internal_api_for_subscription(org)
|
||||||
|
assert len(plans) == 1
|
||||||
|
|
||||||
|
|
||||||
class TestUserSku(ApiTestCase):
|
class TestUserSku(ApiTestCase):
|
||||||
def test_get_user_skus(self):
|
def test_get_user_skus(self):
|
||||||
@ -5171,6 +5185,12 @@ class TestUserSku(ApiTestCase):
|
|||||||
json = self.getJsonResponse(UserSkuList)
|
json = self.getJsonResponse(UserSkuList)
|
||||||
self.assertEqual(len(json), 2)
|
self.assertEqual(len(json), 2)
|
||||||
|
|
||||||
|
def test_quantity(self):
|
||||||
|
self.login(SUBSCRIPTION_USER)
|
||||||
|
subscription_user = model.user.get_user(SUBSCRIPTION_USER)
|
||||||
|
plans = check_internal_api_for_subscription(subscription_user)
|
||||||
|
assert len(plans) == 3
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
@ -239,7 +239,9 @@ class RedHatSubscriptionApi(object):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if convert_to_stripe_plans:
|
if convert_to_stripe_plans:
|
||||||
subscription_list.append(get_plan_using_rh_sku(sku))
|
quantity = user_subscription["quantity"]
|
||||||
|
for i in range(quantity):
|
||||||
|
subscription_list.append(get_plan_using_rh_sku(sku))
|
||||||
else:
|
else:
|
||||||
# add in sku field for convenience
|
# add in sku field for convenience
|
||||||
user_subscription["sku"] = sku
|
user_subscription["sku"] = sku
|
||||||
@ -263,7 +265,7 @@ TEST_USER = {
|
|||||||
"installBaseEndDate": 1707368399000,
|
"installBaseEndDate": 1707368399000,
|
||||||
"webCustomerId": 123456,
|
"webCustomerId": 123456,
|
||||||
"subscriptionNumber": "12399889",
|
"subscriptionNumber": "12399889",
|
||||||
"quantity": 1,
|
"quantity": 2,
|
||||||
"effectiveStartDate": 1707368400000,
|
"effectiveStartDate": 1707368400000,
|
||||||
"effectiveEndDate": 3813177600,
|
"effectiveEndDate": 3813177600,
|
||||||
},
|
},
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import json
|
import json
|
||||||
|
import unittest
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from mock import patch
|
from mock import patch
|
||||||
@ -119,7 +120,7 @@ mocked_subscription_response = [
|
|||||||
"installBaseStartDate": 1705467600000,
|
"installBaseStartDate": 1705467600000,
|
||||||
"installBaseEndDate": 1708145999000,
|
"installBaseEndDate": 1708145999000,
|
||||||
"webCustomerId": 12345,
|
"webCustomerId": 12345,
|
||||||
"quantity": 1,
|
"quantity": 2,
|
||||||
"effectiveStartDate": 1705467600000,
|
"effectiveStartDate": 1705467600000,
|
||||||
"effectiveEndDate": 1708145999000,
|
"effectiveEndDate": 1708145999000,
|
||||||
},
|
},
|
||||||
@ -140,7 +141,7 @@ mocked_subscription_response = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class TestMarketplace:
|
class TestMarketplace(unittest.TestCase):
|
||||||
@patch("requests.request")
|
@patch("requests.request")
|
||||||
def test_timeout_exception(self, requests_mock):
|
def test_timeout_exception(self, requests_mock):
|
||||||
requests_mock.side_effect = requests.exceptions.ReadTimeout()
|
requests_mock.side_effect = requests.exceptions.ReadTimeout()
|
||||||
|
@ -2869,7 +2869,8 @@ CREATE TABLE public.organizationrhskus (
|
|||||||
id integer NOT NULL,
|
id integer NOT NULL,
|
||||||
subscription_id integer NOT NULL,
|
subscription_id integer NOT NULL,
|
||||||
org_id integer NOT NULL,
|
org_id integer NOT NULL,
|
||||||
user_id integer NOT NULL
|
user_id integer NOT NULL,
|
||||||
|
quantity integer
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@ -5569,7 +5570,7 @@ COPY public.accesstokenkind (id, name) FROM stdin;
|
|||||||
--
|
--
|
||||||
|
|
||||||
COPY public.alembic_version (version_num) FROM stdin;
|
COPY public.alembic_version (version_num) FROM stdin;
|
||||||
3f8e3657bb67
|
41d15c93c299
|
||||||
\.
|
\.
|
||||||
|
|
||||||
|
|
||||||
@ -6465,7 +6466,7 @@ COPY public.oauthauthorizationcode (id, application_id, scope, data, code_creden
|
|||||||
-- Data for Name: organizationrhskus; Type: TABLE DATA; Schema: public; Owner: quay
|
-- Data for Name: organizationrhskus; Type: TABLE DATA; Schema: public; Owner: quay
|
||||||
--
|
--
|
||||||
|
|
||||||
COPY public.organizationrhskus (id, subscription_id, org_id, user_id) FROM stdin;
|
COPY public.organizationrhskus (id, subscription_id, org_id, user_id, quantity) FROM stdin;
|
||||||
\.
|
\.
|
||||||
|
|
||||||
|
|
||||||
@ -8083,7 +8084,6 @@ SELECT pg_catalog.setval('public.logentry_id_seq', 1, false);
|
|||||||
-- Name: logentrykind_id_seq; Type: SEQUENCE SET; Schema: public; Owner: quay
|
-- Name: logentrykind_id_seq; Type: SEQUENCE SET; Schema: public; Owner: quay
|
||||||
--
|
--
|
||||||
|
|
||||||
|
|
||||||
SELECT pg_catalog.setval('public.logentrykind_id_seq', 107, true);
|
SELECT pg_catalog.setval('public.logentrykind_id_seq', 107, true);
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user