mirror of https://github.com/portainer/portainer
feat(aci): provide container details page (#4037)
* feat(aci): show basic details * feat(aci): style container details page * fix(aci): fix container ip * feat(aci): provide functions to get single aci resource * feat(aci): show readable data * feat(aci): style container instancepull/4076/head
parent
4b97cf738e
commit
53cddeb283
|
@ -38,6 +38,16 @@ angular.module('portainer.azure', ['portainer.app']).config([
|
|||
},
|
||||
};
|
||||
|
||||
var containerInstance = {
|
||||
name: 'azure.containerinstances.container',
|
||||
url: '/:id',
|
||||
views: {
|
||||
'content@': {
|
||||
component: 'containerInstanceDetails',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
var containerInstanceCreation = {
|
||||
name: 'azure.containerinstances.new',
|
||||
url: '/new/',
|
||||
|
@ -62,6 +72,7 @@ angular.module('portainer.azure', ['portainer.app']).config([
|
|||
|
||||
$stateRegistryProvider.register(azure);
|
||||
$stateRegistryProvider.register(containerInstances);
|
||||
$stateRegistryProvider.register(containerInstance);
|
||||
$stateRegistryProvider.register(containerInstanceCreation);
|
||||
$stateRegistryProvider.register(dashboard);
|
||||
},
|
||||
|
|
|
@ -65,8 +65,8 @@
|
|||
</td>
|
||||
<td>{{ item.Location }}</td>
|
||||
<td>
|
||||
<a ng-if="item.Ports.length > 0" ng-repeat="p in item.Ports" class="image-tag" ng-href="http://{{ item.IPAddress }}:{{ p.port }}" target="_blank">
|
||||
<i class="fa fa-external-link-alt" aria-hidden="true"></i> {{ item.IPAddress }}:{{ p.port }}
|
||||
<a ng-if="item.Ports.length > 0" ng-repeat="p in item.Ports" class="image-tag" ng-href="http://{{ item.IPAddress }}:{{ p.host }}" target="_blank">
|
||||
<i class="fa fa-external-link-alt" aria-hidden="true"></i> {{ item.IPAddress }}:{{ p.host }}
|
||||
</a>
|
||||
<span ng-if="item.Ports.length == 0">-</span>
|
||||
</td>
|
||||
|
|
|
@ -16,11 +16,20 @@ export function ContainerGroupDefaultModel() {
|
|||
}
|
||||
|
||||
export function ContainerGroupViewModel(data) {
|
||||
const addressPorts = data.properties.ipAddress.ports;
|
||||
const container = data.properties.containers.length ? data.properties.containers[0] : {};
|
||||
const containerPorts = container ? container.properties.ports : [];
|
||||
|
||||
this.Id = data.id;
|
||||
this.Name = data.name;
|
||||
this.Location = data.location;
|
||||
this.IPAddress = data.properties.ipAddress.ip;
|
||||
this.Ports = data.properties.ipAddress.ports;
|
||||
this.Ports = addressPorts.length ? addressPorts.map((binding, index) => ({ container: containerPorts[index].port, host: binding.port, protocol: binding.protocol })) : [];
|
||||
this.Image = container.properties.image || '';
|
||||
this.OSType = data.properties.osType;
|
||||
this.AllocatePublicIP = data.properties.ipAddress.type === 'Public';
|
||||
this.CPU = container.properties.resources.requests.cpu;
|
||||
this.Memory = container.properties.resources.requests.memoryInGB;
|
||||
}
|
||||
|
||||
export function CreateContainerGroupRequest(model) {
|
||||
|
|
|
@ -34,12 +34,15 @@ angular.module('portainer.azure').factory('ContainerGroup', [
|
|||
containerGroupName: '@containerGroupName',
|
||||
},
|
||||
},
|
||||
get: {
|
||||
method: 'GET',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
resource.query = base.query;
|
||||
resource.create = withResourceGroup.create;
|
||||
|
||||
resource.get = withResourceGroup.get;
|
||||
return resource;
|
||||
},
|
||||
]);
|
||||
|
|
|
@ -5,13 +5,14 @@ angular.module('portainer.azure').factory('ResourceGroup', [
|
|||
function ResourceGroupFactory($resource, API_ENDPOINT_ENDPOINTS, EndpointProvider) {
|
||||
'use strict';
|
||||
return $resource(
|
||||
API_ENDPOINT_ENDPOINTS + '/:endpointId/azure/subscriptions/:subscriptionId/resourcegroups',
|
||||
API_ENDPOINT_ENDPOINTS + '/:endpointId/azure/subscriptions/:subscriptionId/resourcegroups/:resourceGroupName',
|
||||
{
|
||||
endpointId: EndpointProvider.endpointID,
|
||||
'api-version': '2018-02-01',
|
||||
},
|
||||
{
|
||||
query: { method: 'GET', params: { subscriptionId: '@subscriptionId' } },
|
||||
get: { method: 'GET' },
|
||||
}
|
||||
);
|
||||
},
|
||||
|
|
|
@ -5,13 +5,14 @@ angular.module('portainer.azure').factory('Subscription', [
|
|||
function SubscriptionFactory($resource, API_ENDPOINT_ENDPOINTS, EndpointProvider) {
|
||||
'use strict';
|
||||
return $resource(
|
||||
API_ENDPOINT_ENDPOINTS + '/:endpointId/azure/subscriptions',
|
||||
API_ENDPOINT_ENDPOINTS + '/:endpointId/azure/subscriptions/:id',
|
||||
{
|
||||
endpointId: EndpointProvider.endpointID,
|
||||
'api-version': '2016-06-01',
|
||||
},
|
||||
{
|
||||
query: { method: 'GET' },
|
||||
get: { method: 'GET', params: { id: '@id' } },
|
||||
}
|
||||
);
|
||||
},
|
||||
|
|
|
@ -24,6 +24,12 @@ angular.module('portainer.azure').factory('ContainerGroupService', [
|
|||
return deferred.promise;
|
||||
};
|
||||
|
||||
service.containerGroup = containerGroup;
|
||||
async function containerGroup(subscriptionId, resourceGroupName, containerGroupName) {
|
||||
const containerGroup = await ContainerGroup.get({ subscriptionId, resourceGroupName, containerGroupName }).$promise;
|
||||
return new ContainerGroupViewModel(containerGroup);
|
||||
}
|
||||
|
||||
service.create = function (model, subscriptionId, resourceGroupName) {
|
||||
var payload = new CreateContainerGroupRequest(model);
|
||||
return ContainerGroup.create(
|
||||
|
|
|
@ -24,6 +24,12 @@ angular.module('portainer.azure').factory('ResourceGroupService', [
|
|||
return deferred.promise;
|
||||
};
|
||||
|
||||
service.resourceGroup = resourceGroup;
|
||||
async function resourceGroup(subscriptionId, resourceGroupName) {
|
||||
const group = await ResourceGroup.get({ subscriptionId, resourceGroupName }).$promise;
|
||||
return new ResourceGroupViewModel(group);
|
||||
}
|
||||
|
||||
return service;
|
||||
},
|
||||
]);
|
||||
|
|
|
@ -24,6 +24,12 @@ angular.module('portainer.azure').factory('SubscriptionService', [
|
|||
return deferred.promise;
|
||||
};
|
||||
|
||||
service.subscription = subscription;
|
||||
async function subscription(id) {
|
||||
const subscription = await Subscription.get({ id }).$promise;
|
||||
return new SubscriptionViewModel(subscription);
|
||||
}
|
||||
|
||||
return service;
|
||||
},
|
||||
]);
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
<rd-header>
|
||||
<rd-header-title title-text="Create container instance"></rd-header-title>
|
||||
<rd-header-content> <a ui-sref="azure.containerinstances">Container instances</a> > {{ $ctrl.container.Name }} </rd-header-content>
|
||||
</rd-header>
|
||||
|
||||
<div class="row" ng-if="!$ctrl.state.loading">
|
||||
<div class="col-sm-12">
|
||||
<rd-widget>
|
||||
<rd-widget-body>
|
||||
<div class="form-horizontal" autocomplete="off">
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Azure settings
|
||||
</div>
|
||||
<!-- subscription-input -->
|
||||
<div class="form-group">
|
||||
<label for="azure_subscription" class="col-sm-2 control-label text-left">Subscription</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" ng-model="$ctrl.subscription.Name" disabled />
|
||||
</div>
|
||||
</div>
|
||||
<!-- !subscription-input -->
|
||||
<!-- resourcegroup-input -->
|
||||
<div class="form-group">
|
||||
<label for="azure_resourcegroup" class="col-sm-2 control-label text-left">Resource group</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" ng-model="$ctrl.resourceGroup.Name" disabled />
|
||||
</div>
|
||||
</div>
|
||||
<!-- !resourcegroup-input -->
|
||||
<!-- location-input -->
|
||||
<div class="form-group">
|
||||
<label for="azure_location" class="col-sm-2 control-label text-left">Location</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" ng-model="$ctrl.container.Location" disabled />
|
||||
</div>
|
||||
</div>
|
||||
<!-- !location-input -->
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Container configuration
|
||||
</div>
|
||||
<!-- name-input -->
|
||||
<div class="form-group">
|
||||
<label for="container_name" class="col-sm-2 control-label text-left">Name</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" ng-model="$ctrl.container.Name" disabled />
|
||||
</div>
|
||||
</div>
|
||||
<!-- !name-input -->
|
||||
<!-- image-input -->
|
||||
<div class="form-group">
|
||||
<label for="image_name" class="col-sm-2 control-label text-left">Image</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" ng-model="$ctrl.container.Image" disabled />
|
||||
</div>
|
||||
</div>
|
||||
<!-- !image-input -->
|
||||
<!-- os-input -->
|
||||
<div class="form-group">
|
||||
<label for="container_os" class="col-sm-2 control-label text-left">OS</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" ng-model="$ctrl.container.OSType" disabled />
|
||||
</div>
|
||||
</div>
|
||||
<!-- !os-input -->
|
||||
<!-- port-mapping -->
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label text-left">Port mapping</label>
|
||||
</div>
|
||||
<!-- port-mapping-input-list -->
|
||||
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
|
||||
<div ng-repeat="binding in $ctrl.container.Ports" style="margin-top: 2px;">
|
||||
<!-- host-port -->
|
||||
<div class="input-group col-sm-4 input-group-sm">
|
||||
<span class="input-group-addon">host</span>
|
||||
<input type="text" class="form-control" ng-model="binding.host" placeholder="e.g. 80" disabled />
|
||||
</div>
|
||||
<!-- !host-port -->
|
||||
<span style="margin: 0 10px 0 10px;">
|
||||
<i class="fa fa-long-arrow-alt-right" aria-hidden="true"></i>
|
||||
</span>
|
||||
<!-- container-port -->
|
||||
<div class="input-group col-sm-4 input-group-sm">
|
||||
<span class="input-group-addon">container</span>
|
||||
<input type="text" class="form-control" ng-model="binding.container" placeholder="e.g. 80" disabled />
|
||||
</div>
|
||||
<!-- !container-port -->
|
||||
<!-- protocol-actions -->
|
||||
<div class="input-group col-sm-3 input-group-sm">
|
||||
<div class="btn-group btn-group-sm">
|
||||
<label class="btn btn-primary" ng-model="binding.protocol" uib-btn-radio="'TCP'" disabled>TCP</label>
|
||||
<label class="btn btn-primary" ng-model="binding.protocol" uib-btn-radio="'UDP'" disabled>UDP</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !protocol-actions -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- !port-mapping-input-list -->
|
||||
</div>
|
||||
<!-- !port-mapping -->
|
||||
<!-- public-ip -->
|
||||
<div class="form-group" ng-if="$ctrl.container.AllocatePublicIP">
|
||||
<label for="public_ip" class="col-sm-2 control-label text-left">
|
||||
Public IP
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" ng-model="$ctrl.container.IPAddress" disabled />
|
||||
</div>
|
||||
</div>
|
||||
<!-- public-ip -->
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Container resources
|
||||
</div>
|
||||
<!-- cpu-input -->
|
||||
<div class="form-group">
|
||||
<label for="container_cpu" class="col-sm-2 control-label text-left">CPU</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" ng-model="$ctrl.container.CPU" disabled />
|
||||
</div>
|
||||
</div>
|
||||
<!-- !cpu-input -->
|
||||
<!-- memory-input -->
|
||||
<div class="form-group">
|
||||
<label for="container_memory" class="col-sm-2 control-label text-left">Memory</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" ng-model="$ctrl.container.Memory" disabled />
|
||||
</div>
|
||||
</div>
|
||||
<!-- !memory-input -->
|
||||
</div>
|
||||
</rd-widget-body>
|
||||
</rd-widget>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,36 @@
|
|||
class ContainerInstanceDetailsController {
|
||||
/* @ngInject */
|
||||
constructor($state, AzureService, ContainerGroupService, Notifications, ResourceGroupService, SubscriptionService) {
|
||||
Object.assign(this, { $state, AzureService, ContainerGroupService, Notifications, ResourceGroupService, SubscriptionService });
|
||||
|
||||
this.state = {
|
||||
loading: false,
|
||||
};
|
||||
|
||||
this.container = null;
|
||||
this.subscription = null;
|
||||
this.resourceGroup = null;
|
||||
}
|
||||
|
||||
async $onInit() {
|
||||
this.state.loading = true;
|
||||
const { id } = this.$state.params;
|
||||
const { subscriptionId, resourceGroupId, containerGroupId } = parseId(id);
|
||||
try {
|
||||
this.subscription = await this.SubscriptionService.subscription(subscriptionId);
|
||||
this.container = await this.ContainerGroupService.containerGroup(subscriptionId, resourceGroupId, containerGroupId);
|
||||
this.resourceGroup = await this.ResourceGroupService.resourceGroup(subscriptionId, resourceGroupId);
|
||||
} catch (err) {
|
||||
this.Notifications.error('Failure', err, 'Unable to retrive container instance details');
|
||||
}
|
||||
this.state.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
function parseId(id) {
|
||||
const [, subscriptionId, resourceGroupId, , containerGroupId] = id.match(/^\/subscriptions\/(.+)\/resourceGroups\/(.+)\/providers\/(.+)\/containerGroups\/(.+)$/);
|
||||
|
||||
return { subscriptionId, resourceGroupId, containerGroupId };
|
||||
}
|
||||
|
||||
export default ContainerInstanceDetailsController;
|
|
@ -0,0 +1,6 @@
|
|||
import ContainerInstanceDetailsController from './containerInstanceDetailsController.js';
|
||||
|
||||
angular.module('portainer.azure').component('containerInstanceDetails', {
|
||||
templateUrl: './containerInstanceDetails.html',
|
||||
controller: ContainerInstanceDetailsController,
|
||||
});
|
Loading…
Reference in New Issue