mirror of https://github.com/portainer/portainer
feat(networks): Support multiple excluded IPs for MACVLAN networks (#3962)
* feat(networks): Support multiple excluded IPs for MACVLAN networks * feat(networks): add a generated name * feat(networks): prevent create macvlan network where exclude ip is the same as gateway * feat(networks): remove auxaddresses validation on submit * feat(networks): check exclude ip validation on change * feat(networks): check form validation on change * feat(networks): clean checkAuxiliaryAddress functionpull/4016/merge
parent
08095913a6
commit
c778ef6404
|
@ -21,13 +21,13 @@ angular.module('portainer.docker').controller('CreateNetworkController', [
|
|||
Subnet: '',
|
||||
Gateway: '',
|
||||
IPRange: '',
|
||||
AuxAddress: '',
|
||||
AuxiliaryAddresses: [],
|
||||
},
|
||||
IPV6: {
|
||||
Subnet: '',
|
||||
Gateway: '',
|
||||
IPRange: '',
|
||||
AuxAddress: '',
|
||||
AuxiliaryAddresses: [],
|
||||
},
|
||||
Labels: [],
|
||||
AccessControlData: new AccessControlFormData(),
|
||||
|
@ -79,6 +79,59 @@ angular.module('portainer.docker').controller('CreateNetworkController', [
|
|||
$scope.formValues.Labels.splice(index, 1);
|
||||
};
|
||||
|
||||
$scope.addIPV4AuxAddress = function () {
|
||||
$scope.formValues.IPV4.AuxiliaryAddresses.push('');
|
||||
};
|
||||
|
||||
$scope.addIPV6AuxAddress = function () {
|
||||
$scope.formValues.IPV6.AuxiliaryAddresses.push('');
|
||||
};
|
||||
|
||||
$scope.removeIPV4AuxAddress = function (index) {
|
||||
$scope.formValues.IPV4.AuxiliaryAddresses.splice(index, 1);
|
||||
$scope.state.IPV4AuxiliaryAddressesError.splice(index, 1);
|
||||
};
|
||||
|
||||
$scope.removeIPV6AuxAddress = function (index) {
|
||||
$scope.formValues.IPV6.AuxiliaryAddresses.splice(index, 1);
|
||||
$scope.state.IPV6AuxiliaryAddressesError.splice(index, 1);
|
||||
};
|
||||
|
||||
function checkAuxiliaryAddress(excludedIP, gateway) {
|
||||
const split = _.split(excludedIP, '=');
|
||||
|
||||
if (split.length === 2) {
|
||||
return split[1] === gateway;
|
||||
}
|
||||
return excludedIP === gateway;
|
||||
}
|
||||
|
||||
$scope.checkIPV4AuxiliaryAddress = function (index) {
|
||||
$scope.state.IPV4AuxiliaryAddressesError[index] = checkAuxiliaryAddress($scope.formValues.IPV4.AuxiliaryAddresses[index], $scope.formValues.IPV4.Gateway);
|
||||
};
|
||||
|
||||
$scope.checkIPV6AuxiliaryAddress = function (index) {
|
||||
$scope.state.IPV6AuxiliaryAddressesError[index] = checkAuxiliaryAddress($scope.formValues.IPV6.AuxiliaryAddresses[index], $scope.formValues.IPV6.Gateway);
|
||||
};
|
||||
|
||||
$scope.isValid = function () {
|
||||
const validIPV4 = !_.reduce($scope.state.IPV4AuxiliaryAddressesError, (acc, item) => acc || item, false);
|
||||
const validIPV6 = !_.reduce($scope.state.IPV6AuxiliaryAddressesError, (acc, item) => acc || item, false);
|
||||
return validIPV4 && validIPV6;
|
||||
};
|
||||
|
||||
function prepareAuxiliaryAddresses(ipamConfig, ipFormValues) {
|
||||
ipamConfig.AuxiliaryAddresses = {};
|
||||
_.forEach(ipFormValues.AuxiliaryAddresses, (auxAddress, index) => {
|
||||
const split = _.split(auxAddress, '=');
|
||||
if (split.length === 2) {
|
||||
ipamConfig.AuxiliaryAddresses[split[0]] = split[1];
|
||||
} else {
|
||||
ipamConfig.AuxiliaryAddresses['device' + index] = auxAddress;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function prepareIPAMConfiguration(config) {
|
||||
if ($scope.formValues.IPV4.Subnet) {
|
||||
let ipamConfig = {};
|
||||
|
@ -89,8 +142,8 @@ angular.module('portainer.docker').controller('CreateNetworkController', [
|
|||
if ($scope.formValues.IPV4.IPRange) {
|
||||
ipamConfig.IPRange = $scope.formValues.IPV4.IPRange;
|
||||
}
|
||||
if ($scope.formValues.IPV4.AuxAddress) {
|
||||
ipamConfig.AuxAddress = $scope.formValues.IPV4.AuxAddress;
|
||||
if ($scope.formValues.IPV4.AuxiliaryAddresses.length) {
|
||||
prepareAuxiliaryAddresses(ipamConfig, $scope.formValues.IPV4);
|
||||
}
|
||||
config.IPAM.Config.push(ipamConfig);
|
||||
}
|
||||
|
@ -103,8 +156,8 @@ angular.module('portainer.docker').controller('CreateNetworkController', [
|
|||
if ($scope.formValues.IPV6.IPRange) {
|
||||
ipamConfig.IPRange = $scope.formValues.IPV6.IPRange;
|
||||
}
|
||||
if ($scope.formValues.IPV6.AuxAddress) {
|
||||
ipamConfig.AuxAddress = $scope.formValues.IPV6.AuxAddress;
|
||||
if ($scope.formValues.IPV6.AuxiliaryAddresses.length) {
|
||||
prepareAuxiliaryAddresses(ipamConfig, $scope.formValues.IPV6);
|
||||
}
|
||||
config.EnableIPv6 = true;
|
||||
config.IPAM.Config.push(ipamConfig);
|
||||
|
@ -245,6 +298,8 @@ angular.module('portainer.docker').controller('CreateNetworkController', [
|
|||
|
||||
function initView() {
|
||||
var apiVersion = $scope.applicationState.endpoint.apiVersion;
|
||||
$scope.state.IPV4AuxiliaryAddressesError = [];
|
||||
$scope.state.IPV6AuxiliaryAddressesError = [];
|
||||
|
||||
PluginService.networkPlugins(apiVersion < 1.25)
|
||||
.then(function success(data) {
|
||||
|
|
|
@ -88,12 +88,32 @@
|
|||
<div class="col-sm-4 col-lg-5">
|
||||
<input type="text" class="form-control" ng-model="formValues.IPV4.IPRange" id="ipv4_network_iprange" placeholder="e.g. 172.20.10.128/25" />
|
||||
</div>
|
||||
<label for="ipv4_network_auxaddr" class="col-sm-2 col-lg-1 control-label text-left">Exclude IPs</label>
|
||||
</div>
|
||||
<div ng-repeat="auxAddress in formValues.IPV4.AuxiliaryAddresses track by $index" class="form-group">
|
||||
<label for="ipv4_network_auxaddr_{{ $index }}" class="col-sm-2 col-lg-1 control-label text-left">Exclude IP</label>
|
||||
<div class="col-sm-4 col-lg-5">
|
||||
<input type="text" class="form-control" ng-model="formValues.IPV4.AuxAddress" id="ipv4_network_auxaddr" placeholder="e.g. my-router=172.20.10.129" />
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
ng-model="formValues.IPV4.AuxiliaryAddresses[$index]"
|
||||
ng-change="checkIPV4AuxiliaryAddress($index)"
|
||||
id="ipv4_network_auxaddr_{{ $index }}"
|
||||
placeholder="e.g. my-router=172.20.10.129"
|
||||
/>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-danger" type="button" ng-click="removeIPV4AuxAddress($index)">
|
||||
<i class="fa fa-trash" aria-hidden="true"></i>
|
||||
</button>
|
||||
<div class="col-sm-12 small text-warning" ng-show="state.IPV4AuxiliaryAddressesError[$index]">
|
||||
<p><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> Exclude ip cannot be the same as gateway.</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !iprange-auxaddr-inputs -->
|
||||
<div class="form-group">
|
||||
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addIPV4AuxAddress()">
|
||||
<i class="fa fa-plus-circle" aria-hidden="true"></i> add excluded IP
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-show="config.Driver === 'bridge' || (config.Driver === 'macvlan' && formValues.Macvlan.Scope !== 'swarm')">
|
||||
<div class="col-sm-12 form-section-title">
|
||||
|
@ -117,12 +137,32 @@
|
|||
<div class="col-sm-4 col-lg-5">
|
||||
<input type="text" class="form-control" ng-model="formValues.IPV6.IPRange" id="ipv6_network_iprange" placeholder="e.g. 2001:db8::/64" />
|
||||
</div>
|
||||
<label for="ipv6_network_auxaddr" class="col-sm-2 col-lg-1 control-label text-left">Exclude IPs</label>
|
||||
</div>
|
||||
<div ng-repeat="auxAddress in formValues.IPV6.AuxiliaryAddresses track by $index" class="form-group">
|
||||
<label for="ipv6_network_auxaddr_{{ $index }}" class="col-sm-2 col-lg-1 control-label text-left">Exclude IP</label>
|
||||
<div class="col-sm-4 col-lg-5">
|
||||
<input type="text" class="form-control" ng-model="formValues.IPV6.AuxAddress" id="ipv6_network_auxaddr" placeholder="e.g. my-router=2001:db8::1" />
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
ng-model="formValues.IPV6.AuxiliaryAddresses[$index]"
|
||||
ng-change="checkIPV6AuxiliaryAddress($index)"
|
||||
id="ipv6_network_auxaddr_{{ $index }}"
|
||||
placeholder="e.g. my-router=2001:db8::1"
|
||||
/>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-danger" type="button" ng-click="removeIPV6AuxAddress($index)">
|
||||
<i class="fa fa-trash" aria-hidden="true"></i>
|
||||
</button>
|
||||
<div class="col-sm-12 small text-warning" ng-show="state.IPV6AuxiliaryAddressesError[$index]">
|
||||
<p><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> Exclude ip cannot be the same as gateway.</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !iprange-auxaddr-inputs -->
|
||||
<div class="form-group">
|
||||
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addIPV6AuxAddress()">
|
||||
<i class="fa fa-plus-circle" aria-hidden="true"></i> add excluded IP
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Advanced configuration
|
||||
|
@ -205,7 +245,7 @@
|
|||
<button
|
||||
type="button"
|
||||
class="btn btn-primary btn-sm"
|
||||
ng-disabled="state.actionInProgress || !config.Name || (config.Driver === 'macvlan' && networkCreationForm.$invalid)"
|
||||
ng-disabled="state.actionInProgress || !config.Name || (config.Driver === 'macvlan' && networkCreationForm.$invalid) || !isValid()"
|
||||
ng-click="create()"
|
||||
button-spinner="state.actionInProgress"
|
||||
>
|
||||
|
|
|
@ -47,7 +47,9 @@
|
|||
</tr>
|
||||
<tr ng-if="network.IPAM.IPV4Configs.length > 0" ng-repeat-end>
|
||||
<td>IPV4 IP range - {{ config.IPRange }}</td>
|
||||
<td>IPV4 Excluded Ips - {{ config.AuxAddress }}</td>
|
||||
<td
|
||||
>IPV4 Excluded Ips<span ng-repeat="auxAddress in config.AuxiliaryAddresses"> - {{ auxAddress }}</span></td
|
||||
>
|
||||
</tr>
|
||||
<tr ng-if="network.IPAM.IPV6Configs.length > 0" ng-repeat-start="config in network.IPAM.IPV6Configs">
|
||||
<td>IPV6 Subnet - {{ config.Subnet }}</td>
|
||||
|
@ -55,7 +57,9 @@
|
|||
</tr>
|
||||
<tr ng-if="network.IPAM.IPV6Configs.length > 0" ng-repeat-end>
|
||||
<td>IPV6 IP range - {{ config.IPRange }}</td>
|
||||
<td>IPV6 Excluded Ips - {{ config.AuxAddress }}</td>
|
||||
<td
|
||||
>IPV6 Excluded Ips<span ng-repeat="auxAddress in config.AuxiliaryAddresses"> - {{ auxAddress }}</span></td
|
||||
>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
Loading…
Reference in New Issue