diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index ae5ce6f1..d5f8f01c 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -34,3 +34,13 @@ jobs:
if [[ $(grep -r "^ \{3,\}\(\*\|-\)" website/docs/* | wc -l) -gt 0 ]] ; then \
echo "Too many level of arugments in docs" ; grep -nr "^ \{3,\}\(\*\|-\)" website/docs/* ; exit 1 ; \
fi
+ - name: Check link for pages in sidebar
+ run: |
+ cd website/docs
+ missing=""
+ for i in $(find . -type f | sed 's/^.//' | sed 's/.markdown$//') ; do \
+ grep -q $i ../junos.erb || missing+="Missing link to $i in website sidebar\n" ; \
+ done
+ if [[ ${missing} != "" ]] ; then \
+ echo -e "${missing}" ; exit 1 ; \
+ fi
\ No newline at end of file
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index d2f4a445..a0cf1614 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -1,8 +1,8 @@
name: Go Tests
on: [push, pull_request]
jobs:
- build:
- name: Build
+ build-1_15:
+ name: Build 1.15
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.15
@@ -15,14 +15,28 @@ jobs:
- name: Build
run: go build -v .
+ build-1_16:
+ name: Build 1.16
+ runs-on: ubuntu-latest
+ steps:
+ - name: Set up Go 1.16
+ uses: actions/setup-go@v1
+ with:
+ go-version: 1.16
+ id: go
+ - name: Check out code
+ uses: actions/checkout@v2
+ - name: Build
+ run: go build -v .
+
test:
name: Test
runs-on: ubuntu-latest
steps:
- - name: Set up Go 1.15
+ - name: Set up Go 1.16
uses: actions/setup-go@v1
with:
- go-version: 1.15
+ go-version: 1.16
id: go
- name: Check out code
uses: actions/checkout@v2
diff --git a/.github/workflows/golangci-lint-latest.yml b/.github/workflows/golangci-lint-latest.yml
index 698b3082..dfbaddf6 100644
--- a/.github/workflows/golangci-lint-latest.yml
+++ b/.github/workflows/golangci-lint-latest.yml
@@ -2,7 +2,7 @@ name: GolangCI-Lint-Latest
on:
push:
branches:
- - master
+ - main
jobs:
run:
name: Run
diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml
index 8069082d..a4704cfe 100644
--- a/.github/workflows/golangci-lint.yml
+++ b/.github/workflows/golangci-lint.yml
@@ -10,5 +10,5 @@ jobs:
- name: golangci-lint
uses: golangci/golangci-lint-action@v2
with:
- version: v1.36
+ version: v1.38
args: -c .golangci.yml -v
diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml
index 16edfa53..a42c9fe3 100644
--- a/.github/workflows/releases.yml
+++ b/.github/workflows/releases.yml
@@ -37,15 +37,13 @@ jobs:
goos: [linux, windows, darwin, freebsd]
goarch: [amd64, arm64]
exclude:
- - goos: darwin
- goarch: arm64
- goos: windows
goarch: arm64
steps:
- - name: Set up Go 1.15
+ - name: Set up Go 1.16
uses: actions/setup-go@v1
with:
- go-version: 1.15
+ go-version: 1.16
id: go
- name: Check out code
uses: actions/checkout@v2
@@ -124,3 +122,57 @@ jobs:
asset_path: ./${{ env.REPO_NAME }}_${{ env.RELEASE_VERSION }}_SHA256SUMS
asset_name: ${{ env.REPO_NAME }}_${{ env.RELEASE_VERSION }}_SHA256SUMS
asset_content_type: application/octet-stream
+ website:
+ name: Deploy Website
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+ - name: Clone original Terraform Website
+ run: git clone https://github.com/hashicorp/terraform-website.git /tmp/terraform-website
+ - name: Copy necessary files and co
+ working-directory: ./.terraform-website/
+ run: |
+ cp /tmp/terraform-website/content/config.rb .
+ cp /tmp/terraform-website/content/Gemfile .
+ cp /tmp/terraform-website/content/Gemfile.lock .
+ cp /tmp/terraform-website/content/middleman_helpers.rb .
+ cp -r /tmp/terraform-website/content/source/assets ./source/
+ cp /tmp/terraform-website/content/source/layouts/inner.erb ./source/layouts/
+ echo "redirect 'index.html', to: 'docs/providers/junos/index.html'" >> config.rb
+ - name: Setup ruby
+ uses: actions/setup-ruby@v1
+ with:
+ ruby-version: "2.x"
+ - name: Install middleman
+ working-directory: ./.terraform-website/
+ run: |
+ gem install bundler bundler:1.17.3
+ # json fail with (1.8.3.1) in Gemfile.lock
+ bundle update json --jobs 4 --retry 3
+ bundle install --jobs 4 --retry 3
+ - name: Build Website
+ working-directory: ./.terraform-website/
+ run: bundle exec middleman build --verbose
+ - name: Download google files from S3
+ uses: ItsKarma/aws-cli@v1.70.0
+ with:
+ args: s3 cp s3://terraform-provider-junos.jeremm.fr/google72955f25e01c2a06.html .terraform-website/build/
+ env:
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ - name: Upload Website on S3
+ uses: ItsKarma/aws-cli@v1.70.0
+ with:
+ args: s3 sync .terraform-website/build/ s3://terraform-provider-junos.jeremm.fr/ --delete
+ env:
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ - name: Invalidate Cloudfront Distribution
+ uses: chetan/invalidate-cloudfront-action@v1.3
+ env:
+ PATHS: '/docs/*'
+ AWS_REGION: 'eu-west-1'
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ DISTRIBUTION: ${{ secrets.DISTRIBUTION_ID }}
diff --git a/.github/workflows/terraform-fmt.yml b/.github/workflows/terraform-fmt.yml
index 571739ab..d4c1f0a5 100644
--- a/.github/workflows/terraform-fmt.yml
+++ b/.github/workflows/terraform-fmt.yml
@@ -5,10 +5,10 @@ jobs:
name: terrafmt
runs-on: ubuntu-latest
steps:
- - name: Set up Go 1.15
+ - name: Set up Go 1.16
uses: actions/setup-go@v2
with:
- go-version: 1.15
+ go-version: 1.16
id: go
- name: Check out code
uses: actions/checkout@v2
diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml
index b20daf3c..9d78026f 100644
--- a/.github/workflows/website.yml
+++ b/.github/workflows/website.yml
@@ -2,20 +2,14 @@ name: Website
on:
push:
branches:
- - 'master'
- paths:
- - '.github/workflows/website.yml'
- - '.terraform-website/**'
- - 'website/**'
- release:
- types:
- - published
-
+ - main
jobs:
deploy:
- name: Deploy Website
+ name: Update Website
runs-on: ubuntu-latest
- if: startsWith(github.event.head_commit.message, '[website]')
+ if: |
+ startsWith(github.event.head_commit.message, '[website]') ||
+ (github.event.release.name != '' && github.event.release.draft == false)
steps:
- name: Checkout code
uses: actions/checkout@v2
diff --git a/.golangci.yml b/.golangci.yml
index bbbbd1e5..e474e1e8 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -14,6 +14,8 @@ linters:
- exhaustivestruct
- paralleltest
- gci
+ - cyclop
+ - forcetypeassert
linters-settings:
gocyclo:
# minimal code complexity to report, 30 by default
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 85683041..c51508b5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,31 @@ ENHANCEMENTS:
BUG FIXES:
+## 1.14.0 (March 19, 2021)
+FEATURES:
+* add `junos_chassis_cluster` resource (Fixes parts of [#106](https://github.com/jeremmfr/terraform-provider-junos/issues/106))
+* add `junos_group_dual_system` resource (Fixes [#120](https://github.com/jeremmfr/terraform-provider-junos/issues/120))
+* add `junos_null_commit_file` resource (Fixes parts of [#136](https://github.com/jeremmfr/terraform-provider-junos/issues/136))
+* add `junos_security_address_book` resource (Fixes [#137](https://github.com/jeremmfr/terraform-provider-junos/issues/137)) Thanks [@tagur87](https://github.com/tagur87)
+* add `junos_security_global_policy` resource (Fixes [#138](https://github.com/jeremmfr/terraform-provider-junos/issues/138))
+* add provider argument `file_permission`
+* add provider argument `fake_create_with_setfile` - **Don't use in normal terraform run** and **be carefully with this option**
+See docs for more informations (Fixes parts of [#136](https://github.com/jeremmfr/terraform-provider-junos/issues/136))
+
+ENHANCEMENTS:
+* add `cluster`, `family_evpn` arguments in `junos_bgp_group` and `junos_bgp_neighbor` resource
+* add new `bgp_multipath` block argument to replace `multipath` bool argument in `junos_bgp_group` and `junos_bgp_neighbor` resource
+`bgp_multipath` let add optional arguments. `multipath` is now **deprecated**
+* add `esi` argument in `junos_interface_physical` resource and data source (Fixes [#126](https://github.com/jeremmfr/terraform-provider-junos/issues/126)) Thans [@dejongm](https://github.com/dejongm)
+* add `ether_opts`, `gigether_opts` and `parent_ether_opts` arguments in `junos_interface_physical` resource and data source to add more options and replace `ae_lacp`, `ae_link_speed`, `ae_minimum_links`, `ether802_3ad` arguments which are now deprecated (Fixes [#133](https://github.com/jeremmfr/terraform-provider-junos/issues/133), [#127](https://github.com/jeremmfr/terraform-provider-junos/issues/127), parts of [#106](https://github.com/jeremmfr/terraform-provider-junos/issues/106))
+* add `security_inbound_protocols` and `security_inbound_services` arguments in `junos_interface_logical` resource and data source (Fixes [#141](https://github.com/jeremmfr/terraform-provider-junos/issues/141))
+* add `feature_profile_web_filtering_juniper_enhanced_server` argument in `utm` argument of `junos_security` resource (Fixes [#155](https://github.com/jeremmfr/terraform-provider-junos/issues/155))
+
+BUG FIXES:
+* fix change `description` to null in `junos_interface_logical` and `junos_interface_physical` resource
+* fix `prefix` list order issue in `junos_policyoptions_prefix_list` resource (Fixes [#150](https://github.com/jeremmfr/terraform-provider-junos/issues/150))
+* fix validation for `name` of `address_book` and `address_boob_set` in `junos_security_zone` resource (Fixes [#153](https://github.com/jeremmfr/terraform-provider-junos/issues/153))
+
## 1.13.1 (February 18, 2021)
BUG FIXES:
* fix source nat pool network address not allowed (Fixes [#128](https://github.com/jeremmfr/terraform-provider-junos/issues/128))
diff --git a/README.md b/README.md
index a017686b..15b2861a 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ terraform-provider-junos
[![Installs](https://img.shields.io/badge/dynamic/json?logo=terraform&label=installs&query=$.data.attributes.downloads&url=https%3A%2F%2Fregistry.terraform.io%2Fv2%2Fproviders%2F713)](https://registry.terraform.io/providers/jeremmfr/junos)
[![Registry](https://img.shields.io/badge/registry-doc%40latest-lightgrey?logo=terraform)](https://registry.terraform.io/providers/jeremmfr/junos/latest/docs)
[![Website](https://img.shields.io/badge/website-doc%40latest-lightgrey)](https://terraform-provider-junos.jeremm.fr/)
-[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/jeremmfr/terraform-provider-junos/blob/master/LICENSE)
+[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/jeremmfr/terraform-provider-junos/blob/main/LICENSE)
[![Go Status](https://github.com/jeremmfr/terraform-provider-junos/workflows/Go%20Tests/badge.svg)](https://github.com/jeremmfr/terraform-provider-junos/actions)
[![Lint Status](https://github.com/jeremmfr/terraform-provider-junos/workflows/GolangCI-Lint/badge.svg)](https://github.com/jeremmfr/terraform-provider-junos/actions)
[![Go Report Card](https://goreportcard.com/badge/github.com/jeremmfr/terraform-provider-junos)](https://goreportcard.com/report/github.com/jeremmfr/terraform-provider-junos)
@@ -22,7 +22,7 @@ Requirements
Optional
---
-- [Go](https://golang.org/doc/install) 1.14 (to build the provider plugin)
+- [Go](https://golang.org/doc/install) 1.15 (to build the provider plugin)
Automatic install
---
diff --git a/go.mod b/go.mod
index 7540e185..e4b256c6 100644
--- a/go.mod
+++ b/go.mod
@@ -1,11 +1,11 @@
module terraform-provider-junos
-go 1.14
+go 1.15
require (
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
- github.com/hashicorp/terraform-plugin-sdk/v2 v2.4.0
+ github.com/hashicorp/terraform-plugin-sdk/v2 v2.4.4
github.com/jeremmfr/go-netconf v0.3.1
github.com/jeremmfr/junosdecode v1.0.0
- golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
+ golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83
)
diff --git a/go.sum b/go.sum
index 93f099a2..8f40cf2f 100644
--- a/go.sum
+++ b/go.sum
@@ -3,7 +3,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
-cloud.google.com/go v0.45.1 h1:lRi0CHyU+ytlvylOlFKKq0af6JncuyoRh1J+QJBqQx0=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
@@ -44,7 +43,6 @@ github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/g
github.com/andybalholm/crlf v0.0.0-20171020200849-670099aa064f/go.mod h1:k8feO4+kXDxro6ErPXBRTJ/ro2mf0SsFG8s7doP9kJE=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
-github.com/apparentlymart/go-cidr v1.0.1 h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfTJ/SpF+U=
github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc=
github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0 h1:MzVXffFUye+ZcSR6opIgz9Co7WcDx6ZcY+RjfFHoA0I=
@@ -60,7 +58,6 @@ github.com/aws/aws-sdk-go v1.25.3 h1:uM16hIw9BotjZKMZlX05SN2EFtaWfi/NonPKIARiBLQ
github.com/aws/aws-sdk-go v1.25.3/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
-github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
@@ -98,7 +95,6 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
-github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -106,19 +102,15 @@ github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18h
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
-github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
@@ -133,13 +125,10 @@ github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
-github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@@ -162,13 +151,11 @@ github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/U
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU=
github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg=
-github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI=
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs=
-github.com/hashicorp/go-getter v1.4.0 h1:ENHNi8494porjD0ZhIrjlAHnveSFhY7hvOJrV/fsKkw=
github.com/hashicorp/go-getter v1.4.0/go.mod h1:7qxyCd8rBfcShwsvxgIguu4KbS3l8bUCwg2Umn7RjeY=
github.com/hashicorp/go-getter v1.5.0 h1:ciWJaeZWSMbc5OiLMpKp40MKFPqO44i0h3uyfXPBkkk=
github.com/hashicorp/go-getter v1.5.0/go.mod h1:a7z7NPPfNQpJWcn4rSWFtdrSldqLdLPEF3d8nFMsSLM=
@@ -178,7 +165,6 @@ github.com/hashicorp/go-hclog v0.15.0 h1:qMuK0wxsoW4D0ddCCYwPSTm4KQv1X1ke3WmPWZ0
github.com/hashicorp/go-hclog v0.15.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
-github.com/hashicorp/go-plugin v1.3.0 h1:4d/wJojzvHV1I4i/rrjVaeuyxWrLzDE1mDCyDy8fXS8=
github.com/hashicorp/go-plugin v1.3.0/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0=
github.com/hashicorp/go-plugin v1.4.0 h1:b0O7rs5uiJ99Iu9HugEzsM67afboErkHUWddUSpUO3A=
github.com/hashicorp/go-plugin v1.4.0/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ=
@@ -187,27 +173,23 @@ github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoD
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
-github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI=
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
-github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
-github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl/v2 v2.3.0 h1:iRly8YaMwTBAKhn1Ybk7VSdzbnopghktCD031P8ggUE=
github.com/hashicorp/hcl/v2 v2.3.0/go.mod h1:d+FwDBbOLvpAM3Z6J7gPj/VoAGkNe/gm352ZhjJ/Zv8=
github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
-github.com/hashicorp/terraform-exec v0.12.0 h1:Tb1VC2gqArl9EJziJjoazep2MyxMk00tnNKV/rgMba0=
-github.com/hashicorp/terraform-exec v0.12.0/go.mod h1:SGhto91bVRlgXQWcJ5znSz+29UZIa8kpBbkGwQ+g9E8=
+github.com/hashicorp/terraform-exec v0.13.0 h1:1Pth+pdWJAufJuWWjaVOVNEkoRTOjGn3hQpAqj4aPdg=
+github.com/hashicorp/terraform-exec v0.13.0/go.mod h1:SGhto91bVRlgXQWcJ5znSz+29UZIa8kpBbkGwQ+g9E8=
github.com/hashicorp/terraform-json v0.8.0 h1:XObQ3PgqU52YLQKEaJ08QtUshAfN3yu4u8ebSW0vztc=
github.com/hashicorp/terraform-json v0.8.0/go.mod h1:3defM4kkMfttwiE7VakJDwCd4R+umhSQnvJwORXbprE=
-github.com/hashicorp/terraform-plugin-go v0.1.0 h1:kyXZ0nkHxiRev/q18N40IbRRk4AV0zE/MDJkDM3u8dY=
-github.com/hashicorp/terraform-plugin-go v0.1.0/go.mod h1:10V6F3taeDWVAoLlkmArKttR3IULlRWFAGtQIQTIDr4=
-github.com/hashicorp/terraform-plugin-sdk/v2 v2.4.0 h1:2c+vG46celrDCsfYEIzaXxvBaAXCqlVG77LwtFz8cfs=
-github.com/hashicorp/terraform-plugin-sdk/v2 v2.4.0/go.mod h1:JBItawj+j8Ssla5Ib6BC/W9VQkOucBfnX7VRtyx1vw8=
-github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
+github.com/hashicorp/terraform-plugin-go v0.2.1 h1:EW/R8bB2Zbkjmugzsy1d27yS8/0454b3MtYHkzOknqA=
+github.com/hashicorp/terraform-plugin-go v0.2.1/go.mod h1:10V6F3taeDWVAoLlkmArKttR3IULlRWFAGtQIQTIDr4=
+github.com/hashicorp/terraform-plugin-sdk/v2 v2.4.4 h1:6k0WcxFgVqF/GUFHPvAH8FIrCkoA1RInXzSxhkKamPg=
+github.com/hashicorp/terraform-plugin-sdk/v2 v2.4.4/go.mod h1:z+cMZ0iswzZOahBJ3XmNWgWkVnAd2bl8g+FhyyuPDH4=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
@@ -236,7 +218,6 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
@@ -252,7 +233,6 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
-github.com/mitchellh/cli v1.1.1 h1:J64v/xD7Clql+JVKSvkYojLOXu1ibnY9ZjGLwSt/89w=
github.com/mitchellh/cli v1.1.1/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
@@ -260,7 +240,6 @@ github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
-github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-testing-interface v1.0.4 h1:ZU1VNC02qyufSZsjjs7+khruk2fKvbQ3TwRV/IBCeFA=
github.com/mitchellh/go-testing-interface v1.0.4/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
@@ -269,7 +248,6 @@ github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE=
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
@@ -287,20 +265,16 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ=
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
@@ -317,7 +291,6 @@ github.com/zclconf/go-cty v1.2.1 h1:vGMsygfmeCl4Xb6OA5U5XVAaQZ69FvoG7X2jUtQujb8=
github.com/zclconf/go-cty v1.2.1/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
-go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@@ -328,14 +301,12 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc h1:c0o/qxkaO2LF5t6fQrT4b5hzyggAkLLlCUjqfRxd8Q4=
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
-golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
+golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -379,7 +350,6 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -388,7 +358,6 @@ golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
@@ -399,9 +368,7 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
-golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 h1:Wo7BWFiOk0QRFMLYMqJGFMd9CgUAcGx7V+qEg/h5IBI=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
@@ -422,7 +389,6 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82 h1:vsphBvatvfbhlb4PO1BYSr9dzugGxJ/SQHoNufZJq1w=
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -430,6 +396,7 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -437,7 +404,6 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -446,10 +412,11 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121 h1:rITEj+UZHYC927n8GT97eC3zrpzXdb/voyeOuVKS46o=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
+golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -502,7 +469,6 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
-google.golang.org/api v0.9.0 h1:jbyannxz0XFD3zdjgrSUsaJbgpH4eTrkdhRChkHPfO8=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
@@ -517,23 +483,19 @@ google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
google.golang.org/api v0.29.0 h1:BaiDisFir8O4IJxvAabCGGkQ6yCJegNQqSVoYUNAnbk=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
-google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
-google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19 h1:Lj2SnHtxkRGJDqnGaSjo+CCdIieEnwVazbOXILwQemk=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
@@ -559,18 +521,14 @@ google.golang.org/genproto v0.0.0-20200711021454-869866162049/go.mod h1:FWY/as6D
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
-google.golang.org/grpc v1.21.1 h1:j6XxA85m/6txkUCHvzlV5f+HBNl/1r5cZ2A/3IEFOO8=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
-google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
-google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.32.0 h1:zWTV+LMdc3kaiJMSTOFz2UgSBgx8RNQoTGiZu3fR9S0=
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
@@ -586,7 +544,6 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
diff --git a/junos/config.go b/junos/config.go
index 1af76f29..baa09cd9 100644
--- a/junos/config.go
+++ b/junos/config.go
@@ -1,6 +1,9 @@
package junos
import (
+ "fmt"
+ "strconv"
+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
)
@@ -17,7 +20,9 @@ type Config struct {
junosSSHKeyFile string
junosKeyPass string
junosGroupIntDel string
+ junosFilePermission string
junosDebugNetconfLogPath string
+ junosFakeCreateSetFile string
}
// Session : read session information for Junos Device.
@@ -28,14 +33,40 @@ func (c *Config) Session() (*Session, diag.Diagnostics) {
junosUserName: c.junosUserName,
junosPassword: c.junosPassword,
junosSSHKeyPEM: c.junosSSHKeyPEM,
- junosSSHKeyFile: c.junosSSHKeyFile,
junosKeyPass: c.junosKeyPass,
junosGroupIntDel: c.junosGroupIntDel,
- junosLogFile: c.junosDebugNetconfLogPath,
junosSleepLock: c.junosCmdSleepLock,
junosSleepShort: c.junosCmdSleepShort,
junosSleepSSHClosed: c.junosSSHSleepClosed,
}
+ // junosSSHKeyFile
+ sshKeyFile := c.junosSSHKeyFile
+ if err := replaceTildeToHomeDir(&sshKeyFile); err != nil {
+ return sess, diag.FromErr(err)
+ }
+ sess.junosSSHKeyFile = sshKeyFile
+
+ // junosFilePermission
+ filePermission, err := strconv.ParseInt(c.junosFilePermission, 8, 64)
+ if err != nil {
+ return sess, diag.FromErr(fmt.Errorf("failed to convert value from '%s' to int64 : %w",
+ c.junosFilePermission, err))
+ }
+ sess.junosFilePermission = filePermission
+
+ // junosLogFile
+ junosLogFile := c.junosDebugNetconfLogPath
+ if err := replaceTildeToHomeDir(&junosLogFile); err != nil {
+ return sess, diag.FromErr(err)
+ }
+ sess.junosLogFile = junosLogFile
+
+ // junosFakeCreateSetFile
+ junosFakeCreateSetFile := c.junosFakeCreateSetFile
+ if err := replaceTildeToHomeDir(&junosFakeCreateSetFile); err != nil {
+ return sess, diag.FromErr(err)
+ }
+ sess.junosFakeCreateSetFile = junosFakeCreateSetFile
return sess, nil
}
diff --git a/junos/data_source_interface_logical.go b/junos/data_source_interface_logical.go
index 4dd8846b..79c5b542 100644
--- a/junos/data_source_interface_logical.go
+++ b/junos/data_source_interface_logical.go
@@ -309,6 +309,17 @@ func dataSourceInterfaceLogical() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
+ "security_inbound_protocols": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ "security_inbound_services": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+
"security_zone": {
Type: schema.TypeString,
Computed: true,
diff --git a/junos/data_source_interface_physical.go b/junos/data_source_interface_physical.go
index f8afa19e..4e8d1ef7 100644
--- a/junos/data_source_interface_physical.go
+++ b/junos/data_source_interface_physical.go
@@ -40,20 +40,277 @@ func dataSourceInterfacePhysical() *schema.Resource {
Computed: true,
},
"ae_lacp": {
- Type: schema.TypeString,
- Computed: true,
+ Type: schema.TypeString,
+ Computed: true,
+ Deprecated: "use parent_ether_opts { lacp } instead",
},
"ae_link_speed": {
- Type: schema.TypeString,
- Computed: true,
+ Type: schema.TypeString,
+ Computed: true,
+ Deprecated: "use parent_ether_opts { link_speed } instead",
},
"ae_minimum_links": {
- Type: schema.TypeInt,
+ Type: schema.TypeInt,
+ Computed: true,
+ Deprecated: "use parent_ether_opts { minimum_links } instead",
+ },
+ "esi": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "mode": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "auto_derive_lacp": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "df_election_type": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "identifier": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "source_bmac": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ },
+ },
+ },
+ "ether_opts": {
+ Type: schema.TypeList,
Computed: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "ae_8023ad": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "auto_negotiation": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "no_auto_negotiation": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "flow_control": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "no_flow_control": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "loopback": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "no_loopback": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "redundant_parent": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ },
+ },
},
"ether802_3ad": {
- Type: schema.TypeString,
+ Type: schema.TypeString,
+ Computed: true,
+ Deprecated: "use ether_opts { ae_8023ad } or gigether_opts { ae_8023ad } instead",
+ },
+ "gigether_opts": {
+ Type: schema.TypeList,
Computed: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "ae_8023ad": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "auto_negotiation": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "no_auto_negotiation": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "flow_control": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "no_flow_control": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "loopback": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "no_loopback": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "redundant_parent": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ },
+ },
+ },
+ "parent_ether_opts": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "bfd_liveness_detection": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "local_address": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "authentication_algorithm": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "authentication_key_chain": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "authentication_loose_check": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "detection_time_threshold": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
+ "holddown_interval": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
+ "minimum_interval": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
+ "minimum_receive_interval": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
+ "multiplier": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
+ "neighbor": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "no_adaptation": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "transmit_interval_minimum_interval": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
+ "transmit_interval_threshold": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
+ "version": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ },
+ },
+ },
+ "flow_control": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "no_flow_control": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "lacp": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "mode": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "admin_key": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
+ "periodic": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "sync_reset": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "system_id": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "system_priority": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
+ },
+ },
+ },
+ "loopback": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "no_loopback": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "link_speed": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "minimum_bandwidth": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "minimum_links": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
+ "redundancy_group": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
+ "source_address_filter": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ "source_filtering": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ },
+ },
},
"trunk": {
Type: schema.TypeBool,
diff --git a/junos/func_common.go b/junos/func_common.go
index 4bd455f5..7c3e3bbf 100644
--- a/junos/func_common.go
+++ b/junos/func_common.go
@@ -2,33 +2,22 @@ package junos
import (
"fmt"
- "log"
"net"
"os"
+ "strconv"
"strings"
- "time"
"github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
-func logFile(message string, file string) {
- // create your file with desired read/write permissions
- f, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
- if err != nil {
- log.Fatal(err)
- }
-
- // defer to close when you're done with it, not because you think it's idiomatic!
- defer f.Close()
-
- // set output of logs to f
- log.SetOutput(f)
- log.SetPrefix(time.Now().Format("2006-01-02 15:04:05"))
+type FormatName int
- log.Printf("%s", message)
-}
+const (
+ FormatDefault FormatName = iota
+ FormatAddressName
+)
func appendDiagWarns(diags *diag.Diagnostics, warns []error) {
for _, w := range warns {
@@ -99,7 +88,49 @@ func validateCIDR(cidr string) error {
return nil
}
-func validateNameObjectJunos(exclude []string, length int) schema.SchemaValidateDiagFunc {
+func validateWildcardFunc() schema.SchemaValidateDiagFunc {
+ return func(i interface{}, path cty.Path) diag.Diagnostics {
+ var diags diag.Diagnostics
+ v := i.(string)
+ err := validateWildcardWithMask(v)
+ if err != nil {
+ diags = append(diags, diag.Diagnostic{
+ Severity: diag.Error,
+ Summary: err.Error(),
+ AttributePath: path,
+ })
+ }
+
+ return diags
+ }
+}
+
+func validateWildcardWithMask(wildcard string) error {
+ if !strings.Contains(wildcard, "/") {
+ return fmt.Errorf("%v missing mask", wildcard)
+ }
+ if strings.Contains(wildcard, ":") {
+ return fmt.Errorf("wildcards do not support IPv6 addresses, %v is IPv6", wildcard)
+ }
+ wildcardSplit := strings.Split(wildcard, "/")
+ ip := net.ParseIP(wildcardSplit[0]).To4()
+ if ip == nil {
+ return fmt.Errorf("ip %v not a valid ip address", wildcardSplit[0])
+ }
+ mask := net.ParseIP(wildcardSplit[1]).To4()
+ if mask == nil {
+ return fmt.Errorf("mask %v is improperly formatted, must be in x.x.x.x notation", wildcardSplit[1])
+ }
+ for _, octet := range strings.Split(mask.String(), ".") {
+ if !stringInSlice(octet, []string{"255", "254", "252", "248", "240", "224", "192", "128", "0"}) {
+ return fmt.Errorf("mask %v must be in subnet mask format, octet [%v] is not", mask, octet)
+ }
+ }
+
+ return nil
+}
+
+func validateNameObjectJunos(exclude []string, length int, format FormatName) schema.SchemaValidateDiagFunc {
return func(i interface{}, path cty.Path) diag.Diagnostics {
var diags diag.Diagnostics
v := i.(string)
@@ -110,10 +141,27 @@ func validateNameObjectJunos(exclude []string, length int) schema.SchemaValidate
AttributePath: path,
})
}
- f := func(r rune) bool {
+ f1 := func(r rune) bool {
return (r < 'a' || r > 'z') && (r < 'A' || r > 'Z') && (r < '0' || r > '9') && r != '-' && r != '_'
}
- if strings.IndexFunc(v, f) != -1 {
+ f2 := func(r rune) bool {
+ return (r < 'a' || r > 'z') && (r < 'A' || r > 'Z') && (r < '0' || r > '9') &&
+ r != '-' && r != '_' && r != ':' && r != '.' && r != '/'
+ }
+ resultRune := -1
+ switch format {
+ case FormatDefault:
+ resultRune = strings.IndexFunc(v, f1)
+ case FormatAddressName:
+ resultRune = strings.IndexFunc(v, f2)
+ default:
+ diags = append(diags, diag.Diagnostic{
+ Severity: diag.Error,
+ Summary: "internal error: validateNameObjectJunos function called with a bad argument",
+ AttributePath: path,
+ })
+ }
+ if resultRune != -1 {
diags = append(diags, diag.Diagnostic{
Severity: diag.Error,
Summary: fmt.Sprintf("%s invalid name (bad character)", i),
@@ -150,6 +198,42 @@ func validateAddress() schema.SchemaValidateDiagFunc {
return diags
}
}
+func validateFilePermission() schema.SchemaValidateDiagFunc {
+ return func(i interface{}, path cty.Path) diag.Diagnostics {
+ var diags diag.Diagnostics
+ v, ok := i.(string)
+
+ if !ok {
+ diags = append(diags, diag.Diagnostic{
+ Severity: diag.Error,
+ Summary: "expected type to be string",
+ AttributePath: path,
+ })
+
+ return diags
+ }
+
+ if len(v) > 4 || len(v) < 3 {
+ diags = append(diags, diag.Diagnostic{
+ Severity: diag.Error,
+ Summary: fmt.Sprintf("bad mode for file - string length should be 3 or 4 digits: %s", v),
+ AttributePath: path,
+ })
+ }
+
+ fileMode, err := strconv.ParseInt(v, 8, 64)
+
+ if err != nil || fileMode > 0777 || fileMode < 0 {
+ diags = append(diags, diag.Diagnostic{
+ Severity: diag.Error,
+ Summary: fmt.Sprintf("bad mode for file - must be three octal digits: %s", v),
+ AttributePath: path,
+ })
+ }
+
+ return diags
+ }
+}
func stringInSlice(str string, list []string) bool {
for _, v := range list {
@@ -255,3 +339,15 @@ func checkStringHasPrefixInList(s string, list []string) bool {
return false
}
+
+func replaceTildeToHomeDir(path *string) error {
+ if strings.HasPrefix(*path, "~") {
+ homeDir, err := os.UserHomeDir()
+ if err != nil {
+ return fmt.Errorf("failed to read user home directory : %w", err)
+ }
+ *path = homeDir + strings.TrimPrefix(*path, "~")
+ }
+
+ return nil
+}
diff --git a/junos/func_resource_bgp.go b/junos/func_resource_bgp.go
index d1c8dfcf..206ef241 100644
--- a/junos/func_resource_bgp.go
+++ b/junos/func_resource_bgp.go
@@ -42,6 +42,7 @@ type bgpOptions struct {
authenticationKey string
authenticationKeyChain string
bgpType string // group only
+ cluster string
localAddress string
localAs string
localInterface string
@@ -52,6 +53,8 @@ type bgpOptions struct {
exportPolicy []string
importPolicy []string
bfdLivenessDetection []map[string]interface{}
+ bgpMultipath []map[string]interface{}
+ familyEvpn []map[string]interface{}
familyInet []map[string]interface{}
familyInet6 []map[string]interface{}
gracefulRestart []map[string]interface{}
@@ -90,8 +93,10 @@ func delBgpOpts(d *schema.ResourceData, typebgp string, m interface{}, jnprSess
delPrefix+"authentication-key",
delPrefix+"authentication-key-chain",
delPrefix+"bfd-liveness-detection",
+ delPrefix+"cluster",
delPrefix+"damping",
delPrefix+"export",
+ delPrefix+"family evpn",
delPrefix+"family inet",
delPrefix+"family inet6",
delPrefix+"graceful-restart",
@@ -114,11 +119,7 @@ func delBgpOpts(d *schema.ResourceData, typebgp string, m interface{}, jnprSess
delPrefix+"type",
)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func setBgpOptsSimple(setPrefix string, d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
@@ -150,6 +151,24 @@ func setBgpOptsSimple(setPrefix string, d *schema.ResourceData, m interface{}, j
if d.Get("authentication_key_chain").(string) != "" {
configSet = append(configSet, setPrefix+"authentication-key-chain "+d.Get("authentication_key_chain").(string))
}
+ for _, v := range d.Get("bgp_multipath").([]interface{}) {
+ configSet = append(configSet, setPrefix+"multipath")
+ if v != nil {
+ bgpMultipah := v.(map[string]interface{})
+ if bgpMultipah["allow_protection"].(bool) {
+ configSet = append(configSet, setPrefix+"multipath allow-protection")
+ }
+ if bgpMultipah["disable"].(bool) {
+ configSet = append(configSet, setPrefix+"multipath disable")
+ }
+ if bgpMultipah["multiple_as"].(bool) {
+ configSet = append(configSet, setPrefix+"multipath multiple-as")
+ }
+ }
+ }
+ if v := d.Get("cluster").(string); v != "" {
+ configSet = append(configSet, setPrefix+"cluster "+v)
+ }
if d.Get("damping").(bool) {
configSet = append(configSet, setPrefix+"damping")
}
@@ -247,11 +266,8 @@ func setBgpOptsSimple(setPrefix string, d *schema.ResourceData, m interface{}, j
if d.Get("remove_private").(bool) {
configSet = append(configSet, setPrefix+"remove-private")
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readBgpOptsSimple(item string, confRead *bgpOptions) error {
var err error
@@ -285,6 +301,9 @@ func readBgpOptsSimple(item string, confRead *bgpOptions) error {
if strings.HasPrefix(item, "authentication-key-chain ") {
confRead.authenticationKeyChain = strings.TrimPrefix(item, "authentication-key-chain ")
}
+ if strings.HasPrefix(item, "cluster ") {
+ confRead.cluster = strings.TrimPrefix(item, "cluster ")
+ }
if item == "damping" {
confRead.damping = true
}
@@ -366,8 +385,23 @@ func readBgpOptsSimple(item string, confRead *bgpOptions) error {
if item == "multihop" {
confRead.multihop = true
}
- if item == "multipath" {
+ if strings.HasPrefix(item, "multipath") {
confRead.multipath = true
+ if len(confRead.bgpMultipath) == 0 {
+ confRead.bgpMultipath = append(confRead.bgpMultipath, map[string]interface{}{
+ "allow_protection": false,
+ "disable": false,
+ "multiple_as": false,
+ })
+ }
+ switch {
+ case item == "multipath allow-protection":
+ confRead.bgpMultipath[0]["allow_protection"] = true
+ case item == "multipath disable":
+ confRead.bgpMultipath[0]["disable"] = true
+ case item == "multipath multiple-as":
+ confRead.bgpMultipath[0]["multiple_as"] = true
+ }
}
if item == "no-advertise-peer-as" {
confRead.noAdvertisePeerAs = true
@@ -561,9 +595,12 @@ func setBgpOptsFamily(setPrefix, familyType string, familyOptsList []interface{}
sess := m.(*Session)
configSet := make([]string, 0)
setPrefixFamily := setPrefix + "family "
- if familyType == inetWord {
+ switch familyType {
+ case "evpn":
+ setPrefixFamily += "evpn "
+ case inetWord:
setPrefixFamily += "inet "
- } else if familyType == inet6Word {
+ case inet6Word:
setPrefixFamily += "inet6 "
}
for _, familyOpts := range familyOptsList {
@@ -625,10 +662,12 @@ func readBgpOptsFamily(item, familyType string, opts []map[string]interface{}) (
"prefix_limit": make([]map[string]interface{}, 0, 1),
}
setPrefix := "family "
- if familyType == inetWord {
+ switch familyType {
+ case "evpn":
+ setPrefix += "evpn "
+ case inetWord:
setPrefix += "inet "
- }
- if familyType == inet6Word {
+ case inet6Word:
setPrefix += "inet6 "
}
trimSplit := strings.Split(strings.TrimPrefix(item, setPrefix), " ")
diff --git a/junos/provider.go b/junos/provider.go
index aedd0dc3..6772c319 100644
--- a/junos/provider.go
+++ b/junos/provider.go
@@ -9,27 +9,33 @@ import (
)
const (
- idSeparator = "_-_"
- defaultWord = "default"
- inetWord = "inet"
- inet6Word = "inet6"
- emptyWord = "empty"
- matchWord = "match"
- permitWord = "permit"
- thenWord = "then"
- prefixWord = "prefix"
- actionNoneWord = "none"
- addWord = "add"
- deleteWord = "delete"
- setWord = "set"
- setLineStart = setWord + " "
- st0Word = "st0"
- opsfV2 = "ospf"
- ospfV3 = "ospf3"
- passiveW = "passive"
- discardW = "discard"
- disableW = "disable"
- dynamicDB = "dynamic-db"
+ idSeparator = "_-_"
+ defaultWord = "default"
+ inetWord = "inet"
+ inet6Word = "inet6"
+ emptyWord = "empty"
+ matchWord = "match"
+ permitWord = "permit"
+ thenWord = "then"
+ prefixWord = "prefix"
+ actionNoneWord = "none"
+ addWord = "add"
+ deleteWord = "delete"
+ setWord = "set"
+ setLineStart = setWord + " "
+ st0Word = "st0"
+ opsfV2 = "ospf"
+ ospfV3 = "ospf3"
+ activeW = "active"
+ passiveW = "passive"
+ discardW = "discard"
+ disableW = "disable"
+ dynamicDB = "dynamic-db"
+ preemptWord = "preempt"
+ flowControlWords = "flow-control"
+ noFlowControlWords = "no-flow-control"
+ loopbackWord = "loopback"
+ noLoopbackWord = "no-loopback"
)
var (
@@ -95,11 +101,22 @@ func Provider() *schema.Provider {
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("JUNOS_SLEEP_SSH_CLOSED", 0),
},
+ "file_permission": {
+ Type: schema.TypeString,
+ Optional: true,
+ DefaultFunc: schema.EnvDefaultFunc("JUNOS_FILE_PERMISSION", "644"),
+ ValidateDiagFunc: validateFilePermission(),
+ },
"debug_netconf_log_path": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("JUNOS_LOG_PATH", ""),
},
+ "fake_create_with_setfile": {
+ Type: schema.TypeString,
+ Optional: true,
+ DefaultFunc: schema.EnvDefaultFunc("JUNOS_FAKECREATE_SETFILE", ""),
+ },
},
ResourcesMap: map[string]*schema.Resource{
"junos_aggregate_route": resourceAggregateRoute(),
@@ -107,12 +124,15 @@ func Provider() *schema.Provider {
"junos_application_set": resourceApplicationSet(),
"junos_bgp_group": resourceBgpGroup(),
"junos_bgp_neighbor": resourceBgpNeighbor(),
+ "junos_chassis_cluster": resourceChassisCluster(),
"junos_firewall_filter": resourceFirewallFilter(),
"junos_firewall_policer": resourceFirewallPolicer(),
+ "junos_group_dual_system": resourceGroupDualSystem(),
"junos_interface": resourceInterface(),
"junos_interface_logical": resourceInterfaceLogical(),
"junos_interface_physical": resourceInterfacePhysical(),
"junos_interface_st0_unit": resourceInterfaceSt0Unit(),
+ "junos_null_commit_file": resourceNullCommitFile(),
"junos_ospf_area": resourceOspfArea(),
"junos_policyoptions_as_path": resourcePolicyoptionsAsPath(),
"junos_policyoptions_as_path_group": resourcePolicyoptionsAsPathGroup(),
@@ -123,6 +143,8 @@ func Provider() *schema.Provider {
"junos_routing_instance": resourceRoutingInstance(),
"junos_routing_options": resourceRoutingOptions(),
"junos_security": resourceSecurity(),
+ "junos_security_address_book": resourceSecurityAddressBook(),
+ "junos_security_global_policy": resourceSecurityGlobalPolicy(),
"junos_security_ike_gateway": resourceIkeGateway(),
"junos_security_ike_policy": resourceIkePolicy(),
"junos_security_ike_proposal": resourceIkeProposal(),
@@ -180,7 +202,9 @@ func configureProvider(ctx context.Context, d *schema.ResourceData) (interface{}
junosCmdSleepShort: d.Get("cmd_sleep_short").(int),
junosCmdSleepLock: d.Get("cmd_sleep_lock").(int),
junosSSHSleepClosed: d.Get("ssh_sleep_closed").(int),
+ junosFilePermission: d.Get("file_permission").(string),
junosDebugNetconfLogPath: d.Get("debug_netconf_log_path").(string),
+ junosFakeCreateSetFile: d.Get("fake_create_with_setfile").(string),
}
return config.Session()
diff --git a/junos/provider_test.go b/junos/provider_test.go
index 615b000a..5e9e0263 100644
--- a/junos/provider_test.go
+++ b/junos/provider_test.go
@@ -41,6 +41,9 @@ func testAccPreCheck(t *testing.T) {
if os.Getenv("JUNOS_KEYFILE") == "" && os.Getenv("JUNOS_PASSWORD") == "" && os.Getenv("JUNOS_KEYPEM") == "" {
t.Fatal("JUNOS_KEYPEM, JUNOS_KEYFILE or JUNOS_PASSWORD must be set for acceptance tests")
}
+ if os.Getenv("JUNOS_FAKECREATE_SETFILE") != "" {
+ t.Fatal("can't run testacc with JUNOS_FAKECREATE_SETFILE")
+ }
if err := testAccProvider.Configure(context.Background(), terraform.NewResourceConfigRaw(nil)); err != nil {
t.Fatal(err)
diff --git a/junos/resource_aggregate_route.go b/junos/resource_aggregate_route.go
index deb893e4..321d374b 100644
--- a/junos/resource_aggregate_route.go
+++ b/junos/resource_aggregate_route.go
@@ -46,7 +46,7 @@ func resourceAggregateRoute() *schema.Resource {
Optional: true,
ForceNew: true,
Default: defaultWord,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"active": {
Type: schema.TypeBool,
@@ -96,6 +96,14 @@ func resourceAggregateRoute() *schema.Resource {
func resourceAggregateRouteCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setAggregateRoute(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("destination").(string) + idSeparator + d.Get("routing_instance").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -335,11 +343,8 @@ func setAggregateRoute(d *schema.ResourceData, m interface{}, jnprSess *NetconfO
if d.Get("preference").(int) > 0 {
configSet = append(configSet, setPrefix+" preference "+strconv.Itoa(d.Get("preference").(int)))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readAggregateRoute(destination string, instance string, m interface{},
jnprSess *NetconfObject) (aggregateRouteOptions, error) {
@@ -371,7 +376,7 @@ func readAggregateRoute(destination string, instance string, m interface{},
}
itemTrim := strings.TrimPrefix(item, setLineStart)
switch {
- case itemTrim == "active":
+ case itemTrim == activeW:
confRead.active = true
case itemTrim == "brief":
confRead.brief = true
@@ -413,7 +418,7 @@ func delAggregateRouteOpts(d *schema.ResourceData, m interface{}, jnprSess *Netc
}
delPrefix += d.Get("destination").(string) + " "
configSet = append(configSet,
- delPrefix+"active",
+ delPrefix+activeW,
delPrefix+"brief",
delPrefix+"community",
delPrefix+"discard",
@@ -423,11 +428,8 @@ func delAggregateRouteOpts(d *schema.ResourceData, m interface{}, jnprSess *Netc
delPrefix+"policy",
delPrefix+"preference",
)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func delAggregateRoute(destination string, instance string, m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
@@ -437,11 +439,8 @@ func delAggregateRoute(destination string, instance string, m interface{}, jnprS
} else {
configSet = append(configSet, "delete routing-instances "+instance+" routing-options aggregate route "+destination)
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillAggregateRouteData(d *schema.ResourceData, aggregateRouteOptions aggregateRouteOptions) {
diff --git a/junos/resource_application.go b/junos/resource_application.go
index 0e28e00b..0ab371a8 100644
--- a/junos/resource_application.go
+++ b/junos/resource_application.go
@@ -30,7 +30,7 @@ func resourceApplication() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"destination_port": {
Type: schema.TypeString,
@@ -50,6 +50,14 @@ func resourceApplication() *schema.Resource {
func resourceApplicationCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setApplication(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -226,11 +234,7 @@ func setApplication(d *schema.ResourceData, m interface{}, jnprSess *NetconfObje
configSet = append(configSet, setPrefix+" source-port "+d.Get("source_port").(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readApplication(application string, m interface{}, jnprSess *NetconfObject) (applicationOptions, error) {
sess := m.(*Session)
@@ -268,11 +272,8 @@ func delApplication(d *schema.ResourceData, m interface{}, jnprSess *NetconfObje
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete applications application "+d.Get("name").(string))
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillApplicationData(d *schema.ResourceData, applicationOptions applicationOptions) {
diff --git a/junos/resource_application_set.go b/junos/resource_application_set.go
index db4553c4..f06270e3 100644
--- a/junos/resource_application_set.go
+++ b/junos/resource_application_set.go
@@ -28,7 +28,7 @@ func resourceApplicationSet() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"applications": {
Type: schema.TypeList,
@@ -42,6 +42,14 @@ func resourceApplicationSet() *schema.Resource {
func resourceApplicationSetCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setApplicationSet(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -213,11 +221,7 @@ func setApplicationSet(d *schema.ResourceData, m interface{}, jnprSess *NetconfO
configSet = append(configSet, setPrefix+" application "+v.(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readApplicationSet(applicationSet string, m interface{}, jnprSess *NetconfObject) (applicationSetOptions, error) {
sess := m.(*Session)
@@ -250,11 +254,8 @@ func delApplicationSet(d *schema.ResourceData, m interface{}, jnprSess *NetconfO
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete applications application-set "+d.Get("name").(string))
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillApplicationSetData(d *schema.ResourceData, applicationSetOptions applicationSetOptions) {
diff --git a/junos/resource_bgp_group.go b/junos/resource_bgp_group.go
index 64b1f7d4..cbb36819 100644
--- a/junos/resource_bgp_group.go
+++ b/junos/resource_bgp_group.go
@@ -24,14 +24,14 @@ func resourceBgpGroup() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"routing_instance": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Default: defaultWord,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"type": {
Type: schema.TypeString,
@@ -153,6 +153,33 @@ func resourceBgpGroup() *schema.Resource {
},
},
},
+ "bgp_multipath": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ ConflictsWith: []string{"multipath"},
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "allow_protection": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ "disable": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ "multiple_as": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ },
+ },
+ },
+ "cluster": {
+ Type: schema.TypeString,
+ Optional: true,
+ ValidateFunc: validation.IsIPAddress,
+ },
"damping": {
Type: schema.TypeBool,
Optional: true,
@@ -162,6 +189,76 @@ func resourceBgpGroup() *schema.Resource {
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
+ "family_evpn": {
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "nlri_type": {
+ Type: schema.TypeString,
+ Optional: true,
+ Default: "signaling",
+ ValidateFunc: validation.StringInSlice([]string{"signaling"}, false),
+ },
+ "accepted_prefix_limit": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "maximum": {
+ Type: schema.TypeInt,
+ Required: true,
+ ValidateFunc: validation.IntBetween(1, 4294967295),
+ },
+ "teardown": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(1, 100),
+ },
+ "teardown_idle_timeout": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(1, 2400),
+ },
+ "teardown_idle_timeout_forever": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ },
+ },
+ },
+ "prefix_limit": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "maximum": {
+ Type: schema.TypeInt,
+ Required: true,
+ ValidateFunc: validation.IntBetween(1, 4294967295),
+ },
+ "teardown": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(1, 100),
+ },
+ "teardown_idle_timeout": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(1, 2400),
+ },
+ "teardown_idle_timeout_forever": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
"family_inet": {
Type: schema.TypeList,
Optional: true,
@@ -443,8 +540,10 @@ func resourceBgpGroup() *schema.Resource {
Optional: true,
},
"multipath": {
- Type: schema.TypeBool,
- Optional: true,
+ Type: schema.TypeBool,
+ Optional: true,
+ ConflictsWith: []string{"bgp_multipath"},
+ Deprecated: "use bgp_multipath instead",
},
"out_delay": {
Type: schema.TypeInt,
@@ -475,6 +574,14 @@ func resourceBgpGroup() *schema.Resource {
func resourceBgpGroupCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setBgpGroup(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string) + idSeparator + d.Get("routing_instance").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -691,17 +798,17 @@ func setBgpGroup(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject)
if err := setBgpOptsBfd(setPrefix, d.Get("bfd_liveness_detection").([]interface{}), m, jnprSess); err != nil {
return err
}
- if err := setBgpOptsFamily(setPrefix, inetWord, d.Get("family_inet").([]interface{}), m, jnprSess); err != nil {
+ if err := setBgpOptsFamily(setPrefix, "evpn", d.Get("family_evpn").([]interface{}), m, jnprSess); err != nil {
return err
}
- if err := setBgpOptsFamily(setPrefix, inet6Word, d.Get("family_inet6").([]interface{}), m, jnprSess); err != nil {
+ if err := setBgpOptsFamily(setPrefix, inetWord, d.Get("family_inet").([]interface{}), m, jnprSess); err != nil {
return err
}
- if err := setBgpOptsGrafefulRestart(setPrefix, d.Get("graceful_restart").([]interface{}), m, jnprSess); err != nil {
+ if err := setBgpOptsFamily(setPrefix, inet6Word, d.Get("family_inet6").([]interface{}), m, jnprSess); err != nil {
return err
}
- return nil
+ return setBgpOptsGrafefulRestart(setPrefix, d.Get("graceful_restart").([]interface{}), m, jnprSess)
}
func readBgpGroup(bgpGroup, instance string, m interface{}, jnprSess *NetconfObject) (bgpOptions, error) {
sess := m.(*Session)
@@ -743,12 +850,16 @@ func readBgpGroup(bgpGroup, instance string, m interface{}, jnprSess *NetconfObj
if err != nil {
return confRead, err
}
+ case strings.HasPrefix(itemTrim, "family evpn "):
+ confRead.familyEvpn, err = readBgpOptsFamily(itemTrim, "evpn", confRead.familyEvpn)
+ if err != nil {
+ return confRead, err
+ }
case strings.HasPrefix(itemTrim, "family inet "):
confRead.familyInet, err = readBgpOptsFamily(itemTrim, inetWord, confRead.familyInet)
if err != nil {
return confRead, err
}
-
case strings.HasPrefix(itemTrim, "family inet6 "):
confRead.familyInet6, err = readBgpOptsFamily(itemTrim, inet6Word, confRead.familyInet6)
if err != nil {
@@ -779,11 +890,8 @@ func delBgpGroup(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject)
configSet = append(configSet, "delete routing-instances "+d.Get("routing_instance").(string)+
" protocols bgp group "+d.Get("name").(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillBgpGroupData(d *schema.ResourceData, bgpGroupOptions bgpOptions) {
@@ -823,12 +931,18 @@ func fillBgpGroupData(d *schema.ResourceData, bgpGroupOptions bgpOptions) {
if tfErr := d.Set("bfd_liveness_detection", bgpGroupOptions.bfdLivenessDetection); tfErr != nil {
panic(tfErr)
}
+ if tfErr := d.Set("cluster", bgpGroupOptions.cluster); tfErr != nil {
+ panic(tfErr)
+ }
if tfErr := d.Set("damping", bgpGroupOptions.damping); tfErr != nil {
panic(tfErr)
}
if tfErr := d.Set("export", bgpGroupOptions.exportPolicy); tfErr != nil {
panic(tfErr)
}
+ if tfErr := d.Set("family_evpn", bgpGroupOptions.familyEvpn); tfErr != nil {
+ panic(tfErr)
+ }
if tfErr := d.Set("family_inet", bgpGroupOptions.familyInet); tfErr != nil {
panic(tfErr)
}
@@ -895,8 +1009,14 @@ func fillBgpGroupData(d *schema.ResourceData, bgpGroupOptions bgpOptions) {
if tfErr := d.Set("multihop", bgpGroupOptions.multihop); tfErr != nil {
panic(tfErr)
}
- if tfErr := d.Set("multipath", bgpGroupOptions.multipath); tfErr != nil {
- panic(tfErr)
+ if _, ok := d.GetOk("multipath"); ok {
+ if tfErr := d.Set("multipath", bgpGroupOptions.multipath); tfErr != nil {
+ panic(tfErr)
+ }
+ } else {
+ if tfErr := d.Set("bgp_multipath", bgpGroupOptions.bgpMultipath); tfErr != nil {
+ panic(tfErr)
+ }
}
if tfErr := d.Set("no_advertise_peer_as", bgpGroupOptions.noAdvertisePeerAs); tfErr != nil {
panic(tfErr)
diff --git a/junos/resource_bgp_group_test.go b/junos/resource_bgp_group_test.go
index 70907857..80c9d587 100644
--- a/junos/resource_bgp_group_test.go
+++ b/junos/resource_bgp_group_test.go
@@ -29,6 +29,8 @@ func TestAccJunosBgpGroup_basic(t *testing.T) {
"advertise_peer_as", "true"),
resource.TestCheckResourceAttr("junos_bgp_group.testacc_bgpgroup",
"as_override", "true"),
+ resource.TestCheckResourceAttr("junos_bgp_group.testacc_bgpgroup",
+ "cluster", "192.0.2.3"),
resource.TestCheckResourceAttr("junos_bgp_group.testacc_bgpgroup",
"damping", "true"),
resource.TestCheckResourceAttr("junos_bgp_group.testacc_bgpgroup",
@@ -36,7 +38,7 @@ func TestAccJunosBgpGroup_basic(t *testing.T) {
resource.TestCheckResourceAttr("junos_bgp_group.testacc_bgpgroup",
"mtu_discovery", "true"),
resource.TestCheckResourceAttr("junos_bgp_group.testacc_bgpgroup",
- "multipath", "true"),
+ "bgp_multipath.#", "1"),
resource.TestCheckResourceAttr("junos_bgp_group.testacc_bgpgroup",
"remove_private", "true"),
resource.TestCheckResourceAttr("junos_bgp_group.testacc_bgpgroup",
@@ -140,6 +142,10 @@ func TestAccJunosBgpGroup_basic(t *testing.T) {
"type", "internal"),
resource.TestCheckResourceAttr("junos_bgp_group.testacc_bgpgroup",
"advertise_external_conditional", "true"),
+ resource.TestCheckResourceAttr("junos_bgp_group.testacc_bgpgroup",
+ "bgp_multipath.#", "1"),
+ resource.TestCheckResourceAttr("junos_bgp_group.testacc_bgpgroup",
+ "bgp_multipath.0.multiple_as", "true"),
resource.TestCheckResourceAttr("junos_bgp_group.testacc_bgpgroup",
"no_advertise_peer_as", "true"),
resource.TestCheckResourceAttr("junos_bgp_group.testacc_bgpgroup",
@@ -209,15 +215,16 @@ resource junos_policyoptions_policy_statement "testacc_bgpgroup" {
}
}
resource junos_bgp_group "testacc_bgpgroup" {
- name = "testacc_bgpgroup"
- routing_instance = junos_routing_instance.testacc_bgpgroup.name
- advertise_inactive = true
- advertise_peer_as = true
- as_override = true
+ name = "testacc_bgpgroup"
+ routing_instance = junos_routing_instance.testacc_bgpgroup.name
+ advertise_inactive = true
+ advertise_peer_as = true
+ as_override = true
+ bgp_multipath {}
+ cluster = "192.0.2.3"
damping = true
log_updown = true
mtu_discovery = true
- multipath = true
remove_private = true
passive = true
hold_time = 30
@@ -310,12 +317,14 @@ resource junos_bgp_group "testacc_bgpgroup" {
metric_out_igp_delay_med_update = true
authentication_key = "password"
type = "internal"
+ bgp_multipath {
+ multiple_as = true
+ }
graceful_restart {
restart_time = 10
stale_route_time = 10
}
}
-
`
}
func testAccJunosBgpGroupConfigUpdate2() string {
@@ -329,6 +338,18 @@ resource junos_bgp_group "testacc_bgpgroup" {
local_as_no_prepend_global_as = true
metric_out_minimum_igp_offset = -10
type = "internal"
+ family_evpn {
+ accepted_prefix_limit {
+ maximum = 2
+ teardown = 50
+ teardown_idle_timeout = 30
+ }
+ prefix_limit {
+ maximum = 2
+ teardown = 50
+ teardown_idle_timeout = 30
+ }
+ }
}
`
}
@@ -339,6 +360,7 @@ resource junos_bgp_group "testacc_bgpgroup" {
local_as = "65000"
local_as_alias = true
metric_out_minimum_igp = true
+ family_evpn {}
}
`
}
diff --git a/junos/resource_bgp_neighbor.go b/junos/resource_bgp_neighbor.go
index 0ea46b88..c4eedefd 100644
--- a/junos/resource_bgp_neighbor.go
+++ b/junos/resource_bgp_neighbor.go
@@ -31,13 +31,13 @@ func resourceBgpNeighbor() *schema.Resource {
Optional: true,
ForceNew: true,
Default: defaultWord,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"group": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"accept_remote_nexthop": {
Type: schema.TypeBool,
@@ -151,6 +151,33 @@ func resourceBgpNeighbor() *schema.Resource {
},
},
},
+ "bgp_multipath": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ ConflictsWith: []string{"multipath"},
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "allow_protection": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ "disable": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ "multiple_as": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ },
+ },
+ },
+ "cluster": {
+ Type: schema.TypeString,
+ Optional: true,
+ ValidateFunc: validation.IsIPAddress,
+ },
"damping": {
Type: schema.TypeBool,
Optional: true,
@@ -160,6 +187,76 @@ func resourceBgpNeighbor() *schema.Resource {
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
+ "family_evpn": {
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "nlri_type": {
+ Type: schema.TypeString,
+ Optional: true,
+ Default: "signaling",
+ ValidateFunc: validation.StringInSlice([]string{"signaling"}, false),
+ },
+ "accepted_prefix_limit": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "maximum": {
+ Type: schema.TypeInt,
+ Required: true,
+ ValidateFunc: validation.IntBetween(1, 4294967295),
+ },
+ "teardown": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(1, 100),
+ },
+ "teardown_idle_timeout": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(1, 2400),
+ },
+ "teardown_idle_timeout_forever": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ },
+ },
+ },
+ "prefix_limit": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "maximum": {
+ Type: schema.TypeInt,
+ Required: true,
+ ValidateFunc: validation.IntBetween(1, 4294967295),
+ },
+ "teardown": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(1, 100),
+ },
+ "teardown_idle_timeout": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(1, 2400),
+ },
+ "teardown_idle_timeout_forever": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
"family_inet": {
Type: schema.TypeList,
Optional: true,
@@ -437,8 +534,10 @@ func resourceBgpNeighbor() *schema.Resource {
Optional: true,
},
"multipath": {
- Type: schema.TypeBool,
- Optional: true,
+ Type: schema.TypeBool,
+ Optional: true,
+ ConflictsWith: []string{"bgp_multipath"},
+ Deprecated: "use bgp_multipath instead",
},
"out_delay": {
Type: schema.TypeInt,
@@ -469,6 +568,16 @@ func resourceBgpNeighbor() *schema.Resource {
func resourceBgpNeighborCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setBgpNeighbor(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("ip").(string) +
+ idSeparator + d.Get("routing_instance").(string) +
+ idSeparator + d.Get("group").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -692,17 +801,17 @@ func setBgpNeighbor(d *schema.ResourceData, m interface{}, jnprSess *NetconfObje
if err := setBgpOptsBfd(setPrefix, d.Get("bfd_liveness_detection").([]interface{}), m, jnprSess); err != nil {
return err
}
- if err := setBgpOptsFamily(setPrefix, inetWord, d.Get("family_inet").([]interface{}), m, jnprSess); err != nil {
+ if err := setBgpOptsFamily(setPrefix, "evpn", d.Get("family_evpn").([]interface{}), m, jnprSess); err != nil {
return err
}
- if err := setBgpOptsFamily(setPrefix, inet6Word, d.Get("family_inet6").([]interface{}), m, jnprSess); err != nil {
+ if err := setBgpOptsFamily(setPrefix, inetWord, d.Get("family_inet").([]interface{}), m, jnprSess); err != nil {
return err
}
- if err := setBgpOptsGrafefulRestart(setPrefix, d.Get("graceful_restart").([]interface{}), m, jnprSess); err != nil {
+ if err := setBgpOptsFamily(setPrefix, inet6Word, d.Get("family_inet6").([]interface{}), m, jnprSess); err != nil {
return err
}
- return nil
+ return setBgpOptsGrafefulRestart(setPrefix, d.Get("graceful_restart").([]interface{}), m, jnprSess)
}
func readBgpNeighbor(ip, instance, group string, m interface{}, jnprSess *NetconfObject) (bgpOptions, error) {
sess := m.(*Session)
@@ -743,12 +852,16 @@ func readBgpNeighbor(ip, instance, group string, m interface{}, jnprSess *Netcon
}
itemTrim := strings.TrimPrefix(item, setLineStart)
switch {
+ case strings.HasPrefix(itemTrim, "family evpn "):
+ confRead.familyEvpn, err = readBgpOptsFamily(itemTrim, "evpn", confRead.familyEvpn)
+ if err != nil {
+ return confRead, err
+ }
case strings.HasPrefix(itemTrim, "family inet "):
confRead.familyInet, err = readBgpOptsFamily(itemTrim, inetWord, confRead.familyInet)
if err != nil {
return confRead, err
}
-
case strings.HasPrefix(itemTrim, "family inet6 "):
confRead.familyInet6, err = readBgpOptsFamily(itemTrim, inet6Word, confRead.familyInet6)
if err != nil {
@@ -788,11 +901,8 @@ func delBgpNeighbor(d *schema.ResourceData, m interface{}, jnprSess *NetconfObje
" protocols bgp group "+d.Get("group").(string)+
" neighbor "+d.Get("ip").(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillBgpNeighborData(d *schema.ResourceData, bgpNeighborOptions bgpOptions) {
@@ -835,12 +945,18 @@ func fillBgpNeighborData(d *schema.ResourceData, bgpNeighborOptions bgpOptions)
if tfErr := d.Set("bfd_liveness_detection", bgpNeighborOptions.bfdLivenessDetection); tfErr != nil {
panic(tfErr)
}
+ if tfErr := d.Set("cluster", bgpNeighborOptions.cluster); tfErr != nil {
+ panic(tfErr)
+ }
if tfErr := d.Set("damping", bgpNeighborOptions.damping); tfErr != nil {
panic(tfErr)
}
if tfErr := d.Set("export", bgpNeighborOptions.exportPolicy); tfErr != nil {
panic(tfErr)
}
+ if tfErr := d.Set("family_evpn", bgpNeighborOptions.familyEvpn); tfErr != nil {
+ panic(tfErr)
+ }
if tfErr := d.Set("family_inet", bgpNeighborOptions.familyInet); tfErr != nil {
panic(tfErr)
}
@@ -907,8 +1023,14 @@ func fillBgpNeighborData(d *schema.ResourceData, bgpNeighborOptions bgpOptions)
if tfErr := d.Set("multihop", bgpNeighborOptions.multihop); tfErr != nil {
panic(tfErr)
}
- if tfErr := d.Set("multipath", bgpNeighborOptions.multipath); tfErr != nil {
- panic(tfErr)
+ if _, ok := d.GetOk("multipath"); ok {
+ if tfErr := d.Set("multipath", bgpNeighborOptions.multipath); tfErr != nil {
+ panic(tfErr)
+ }
+ } else {
+ if tfErr := d.Set("bgp_multipath", bgpNeighborOptions.bgpMultipath); tfErr != nil {
+ panic(tfErr)
+ }
}
if tfErr := d.Set("no_advertise_peer_as", bgpNeighborOptions.noAdvertisePeerAs); tfErr != nil {
panic(tfErr)
diff --git a/junos/resource_bgp_neighbor_test.go b/junos/resource_bgp_neighbor_test.go
index ed140ce6..6e005173 100644
--- a/junos/resource_bgp_neighbor_test.go
+++ b/junos/resource_bgp_neighbor_test.go
@@ -29,6 +29,8 @@ func TestAccJunosBgpNeighbor_basic(t *testing.T) {
"advertise_peer_as", "true"),
resource.TestCheckResourceAttr("junos_bgp_neighbor.testacc_bgpneighbor",
"as_override", "true"),
+ resource.TestCheckResourceAttr("junos_bgp_neighbor.testacc_bgpneighbor",
+ "cluster", "192.0.2.3"),
resource.TestCheckResourceAttr("junos_bgp_neighbor.testacc_bgpneighbor",
"damping", "true"),
resource.TestCheckResourceAttr("junos_bgp_neighbor.testacc_bgpneighbor",
@@ -36,7 +38,7 @@ func TestAccJunosBgpNeighbor_basic(t *testing.T) {
resource.TestCheckResourceAttr("junos_bgp_neighbor.testacc_bgpneighbor",
"mtu_discovery", "true"),
resource.TestCheckResourceAttr("junos_bgp_neighbor.testacc_bgpneighbor",
- "multipath", "true"),
+ "bgp_multipath.#", "1"),
resource.TestCheckResourceAttr("junos_bgp_neighbor.testacc_bgpneighbor",
"remove_private", "true"),
resource.TestCheckResourceAttr("junos_bgp_neighbor.testacc_bgpneighbor",
@@ -145,6 +147,10 @@ func TestAccJunosBgpNeighbor_basic(t *testing.T) {
"group", "testacc_bgpneighbor"),
resource.TestCheckResourceAttr("junos_bgp_neighbor.testacc_bgpneighbor",
"advertise_external_conditional", "true"),
+ resource.TestCheckResourceAttr("junos_bgp_neighbor.testacc_bgpneighbor",
+ "bgp_multipath.#", "1"),
+ resource.TestCheckResourceAttr("junos_bgp_neighbor.testacc_bgpneighbor",
+ "bgp_multipath.0.multiple_as", "true"),
resource.TestCheckResourceAttr("junos_bgp_neighbor.testacc_bgpneighbor",
"no_advertise_peer_as", "true"),
resource.TestCheckResourceAttr("junos_bgp_neighbor.testacc_bgpneighbor",
@@ -179,9 +185,9 @@ func TestAccJunosBgpNeighbor_basic(t *testing.T) {
{
Config: testAccJunosBgpNeighborConfigUpdate3(),
Check: resource.ComposeTestCheckFunc(
- resource.TestCheckResourceAttr("junos_bgp_neighbor.testacc_bgpneighbor3",
+ resource.TestCheckResourceAttr("junos_bgp_neighbor.testacc_bgpneighbor2",
"local_as_alias", "true"),
- resource.TestCheckResourceAttr("junos_bgp_neighbor.testacc_bgpneighbor3",
+ resource.TestCheckResourceAttr("junos_bgp_neighbor.testacc_bgpneighbor2",
"metric_out_minimum_igp", "true"),
),
},
@@ -193,6 +199,9 @@ func TestAccJunosBgpNeighbor_basic(t *testing.T) {
func testAccJunosBgpConfigPreCreate() string {
return `
resource junos_routing_options "testacc_routing_options" {
+ autonomous_system {
+ number = "65001"
+ }
graceful_restart {}
}
`
@@ -215,16 +224,17 @@ resource junos_bgp_group "testacc_bgpneighbor" {
routing_instance = junos_routing_instance.testacc_bgpneighbor.name
}
resource junos_bgp_neighbor "testacc_bgpneighbor" {
- ip = "192.0.2.4"
- routing_instance = junos_routing_instance.testacc_bgpneighbor.name
- group = junos_bgp_group.testacc_bgpneighbor.name
- advertise_inactive = true
- advertise_peer_as = true
- as_override = true
+ ip = "192.0.2.4"
+ routing_instance = junos_routing_instance.testacc_bgpneighbor.name
+ group = junos_bgp_group.testacc_bgpneighbor.name
+ advertise_inactive = true
+ advertise_peer_as = true
+ as_override = true
+ bgp_multipath {}
+ cluster = "192.0.2.3"
damping = true
log_updown = true
mtu_discovery = true
- multipath = true
remove_private = true
passive = true
hold_time = 30
@@ -322,6 +332,9 @@ resource junos_bgp_neighbor "testacc_bgpneighbor" {
metric_out_igp_offset = -10
metric_out_igp_delay_med_update = true
authentication_key = "password"
+ bgp_multipath {
+ multiple_as = true
+ }
graceful_restart {
restart_time = 10
stale_route_time = 10
@@ -352,26 +365,55 @@ resource junos_bgp_neighbor "testacc_bgpneighbor2" {
local_as_no_prepend_global_as = true
metric_out_minimum_igp_offset = -10
}
+resource junos_bgp_group "testacc_bgpneighbor2b" {
+ name = "testacc_bgpneighbor2b"
+ type = "internal"
+}
+resource junos_bgp_neighbor "testacc_bgpneighbor2b" {
+ ip = "192.0.2.5"
+ group = junos_bgp_group.testacc_bgpneighbor2b.name
+ family_evpn {
+ accepted_prefix_limit {
+ maximum = 2
+ teardown = 50
+ teardown_idle_timeout = 30
+ }
+ prefix_limit {
+ maximum = 2
+ teardown = 50
+ teardown_idle_timeout = 30
+ }
+ }
+}
`
}
func testAccJunosBgpNeighborConfigUpdate3() string {
return `
-resource junos_routing_instance "testacc_bgpneighbor3" {
- name = "testacc_bgpneighbor3"
+resource junos_routing_instance "testacc_bgpneighbor2" {
+ name = "testacc_bgpneighbor2"
as = "65000"
}
-resource junos_bgp_group "testacc_bgpneighbor3" {
- name = "testacc_bgpneighbor3"
- routing_instance = junos_routing_instance.testacc_bgpneighbor3.name
+resource junos_bgp_group "testacc_bgpneighbor2" {
+ name = "testacc_bgpneighbor2"
+ routing_instance = junos_routing_instance.testacc_bgpneighbor2.name
type = "internal"
}
-resource junos_bgp_neighbor "testacc_bgpneighbor3" {
+resource junos_bgp_neighbor "testacc_bgpneighbor2" {
ip = "192.0.2.4"
- routing_instance = junos_routing_instance.testacc_bgpneighbor3.name
- group = junos_bgp_group.testacc_bgpneighbor3.name
+ routing_instance = junos_routing_instance.testacc_bgpneighbor2.name
+ group = junos_bgp_group.testacc_bgpneighbor2.name
local_as = "65000"
local_as_alias = true
metric_out_minimum_igp = true
}
+resource junos_bgp_group "testacc_bgpneighbor2b" {
+ name = "testacc_bgpneighbor2b"
+ type = "internal"
+}
+resource junos_bgp_neighbor "testacc_bgpneighbor2b" {
+ ip = "192.0.2.5"
+ group = junos_bgp_group.testacc_bgpneighbor2b.name
+ family_evpn {}
+}
`
}
diff --git a/junos/resource_chassis_cluster.go b/junos/resource_chassis_cluster.go
new file mode 100644
index 00000000..e9170019
--- /dev/null
+++ b/junos/resource_chassis_cluster.go
@@ -0,0 +1,581 @@
+package junos
+
+import (
+ "context"
+ "fmt"
+ "strconv"
+ "strings"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
+)
+
+type chassisClusterOptions struct {
+ configSyncNoSecBootAuto bool
+ controlLinkRecovery bool
+ heartbeatInterval int
+ heartbeatThreshold int
+ rethCount int
+ redundancyGroup []map[string]interface{}
+ fab0 []map[string]interface{}
+ fab1 []map[string]interface{}
+}
+
+func resourceChassisCluster() *schema.Resource {
+ return &schema.Resource{
+ CreateContext: resourceChassisClusterCreate,
+ ReadContext: resourceChassisClusterRead,
+ UpdateContext: resourceChassisClusterUpdate,
+ DeleteContext: resourceChassisClusterDelete,
+ Importer: &schema.ResourceImporter{
+ State: resourceChassisClusterImport,
+ },
+ Schema: map[string]*schema.Schema{
+ "fab0": {
+ Type: schema.TypeList,
+ Required: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "member_interfaces": {
+ Type: schema.TypeList,
+ Required: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ "description": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ },
+ },
+ },
+ "fab1": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "member_interfaces": {
+ Type: schema.TypeList,
+ Required: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ "description": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ },
+ },
+ },
+ "redundancy_group": {
+ Type: schema.TypeList,
+ Required: true,
+ MaxItems: 128,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "node0_priority": {
+ Type: schema.TypeInt,
+ Required: true,
+ ValidateFunc: validation.IntBetween(1, 254),
+ },
+ "node1_priority": {
+ Type: schema.TypeInt,
+ Required: true,
+ ValidateFunc: validation.IntBetween(1, 254),
+ },
+ "gratuitous_arp_count": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(1, 16),
+ },
+ "hold_down_interval": {
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: -1,
+ ValidateFunc: validation.IntBetween(0, 1800),
+ },
+ "interface_monitor": {
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "name": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "weight": {
+ Type: schema.TypeInt,
+ Required: true,
+ ValidateFunc: validation.IntBetween(0, 255),
+ },
+ },
+ },
+ },
+ "preempt": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ },
+ },
+ },
+ "reth_count": {
+ Type: schema.TypeInt,
+ Required: true,
+ ValidateFunc: validation.IntBetween(1, 128),
+ },
+ "config_sync_no_secondary_bootup_auto": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ "control_link_recovery": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ "heartbeat_interval": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(1000, 2000),
+ },
+ "heartbeat_threshold": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(3, 8),
+ },
+ },
+ }
+}
+
+func checkCompatibilityChassisCluster(jnprSess *NetconfObject) bool {
+ if strings.HasPrefix(strings.ToLower(jnprSess.SystemInformation.HardwareModel), "srx") {
+ return true
+ }
+ if strings.HasPrefix(strings.ToLower(jnprSess.SystemInformation.HardwareModel), "vsrx") {
+ return true
+ }
+ if strings.HasPrefix(strings.ToLower(jnprSess.SystemInformation.HardwareModel), "j") {
+ return true
+ }
+
+ return false
+}
+
+func resourceChassisClusterCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setChassisCluster(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId("cluster")
+
+ return nil
+ }
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ defer sess.closeSession(jnprSess)
+ if !checkCompatibilityChassisCluster(jnprSess) {
+ return diag.FromErr(fmt.Errorf("chassis cluster "+
+ "not compatible with Junos device %s", jnprSess.SystemInformation.HardwareModel))
+ }
+ sess.configLock(jnprSess)
+ if err := setChassisCluster(d, m, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ var diagWarns diag.Diagnostics
+ warns, err := sess.commitConf("create resource junos_chassis_cluster", jnprSess)
+ appendDiagWarns(&diagWarns, warns)
+ if err != nil {
+ sess.configClear(jnprSess)
+
+ return append(diagWarns, diag.FromErr(err)...)
+ }
+ d.SetId("cluster")
+
+ return append(diagWarns, resourceChassisClusterReadWJnprSess(d, m, jnprSess)...)
+}
+func resourceChassisClusterRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ sess := m.(*Session)
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ defer sess.closeSession(jnprSess)
+
+ return resourceChassisClusterReadWJnprSess(d, m, jnprSess)
+}
+func resourceChassisClusterReadWJnprSess(
+ d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) diag.Diagnostics {
+ mutex.Lock()
+ clusterOptions, err := readChassisCluster(m, jnprSess)
+ mutex.Unlock()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ fillChassisCluster(d, clusterOptions)
+
+ return nil
+}
+func resourceChassisClusterUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ d.Partial(true)
+ sess := m.(*Session)
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ defer sess.closeSession(jnprSess)
+ sess.configLock(jnprSess)
+ if err := delChassisCluster(m, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ if err := setChassisCluster(d, m, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ var diagWarns diag.Diagnostics
+ warns, err := sess.commitConf("update resource junos_chassis_cluster", jnprSess)
+ appendDiagWarns(&diagWarns, warns)
+ if err != nil {
+ sess.configClear(jnprSess)
+
+ return append(diagWarns, diag.FromErr(err)...)
+ }
+ d.Partial(false)
+
+ return append(diagWarns, resourceChassisClusterReadWJnprSess(d, m, jnprSess)...)
+}
+func resourceChassisClusterDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ sess := m.(*Session)
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ defer sess.closeSession(jnprSess)
+ sess.configLock(jnprSess)
+ if err := delChassisCluster(m, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ var diagWarns diag.Diagnostics
+ warns, err := sess.commitConf("delete resource junos_chassis_cluster", jnprSess)
+ appendDiagWarns(&diagWarns, warns)
+ if err != nil {
+ sess.configClear(jnprSess)
+
+ return append(diagWarns, diag.FromErr(err)...)
+ }
+
+ return diagWarns
+}
+func resourceChassisClusterImport(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) {
+ sess := m.(*Session)
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return nil, err
+ }
+ defer sess.closeSession(jnprSess)
+ result := make([]*schema.ResourceData, 1)
+ clusterOptions, err := readChassisCluster(m, jnprSess)
+ if err != nil {
+ return nil, err
+ }
+ fillChassisCluster(d, clusterOptions)
+ d.SetId("cluster")
+ result[0] = d
+
+ return result, nil
+}
+
+func setChassisCluster(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
+ sess := m.(*Session)
+ configSet := make([]string, 0)
+
+ setIntPrefix := "set interfaces "
+ for _, v := range d.Get("fab0").([]interface{}) {
+ configSet = append(configSet, "delete interfaces fab0 disable")
+ fab0 := v.(map[string]interface{})
+ for _, v2 := range fab0["member_interfaces"].([]interface{}) {
+ configSet = append(configSet, setIntPrefix+
+ "fab0 fabric-options member-interfaces "+v2.(string))
+ }
+ if fab0["description"].(string) != "" {
+ configSet = append(configSet, setIntPrefix+"fab0 description \""+
+ fab0["description"].(string)+"\"")
+ }
+ }
+ for _, v := range d.Get("fab1").([]interface{}) {
+ configSet = append(configSet, "delete interfaces fab1 disable")
+ fab0 := v.(map[string]interface{})
+ for _, v2 := range fab0["member_interfaces"].([]interface{}) {
+ configSet = append(configSet, setIntPrefix+
+ "fab1 fabric-options member-interfaces "+v2.(string))
+ }
+ if fab0["description"].(string) != "" {
+ configSet = append(configSet, setIntPrefix+"fab1 description \""+
+ fab0["description"].(string)+"\"")
+ }
+ }
+
+ setChassisluster := "set chassis cluster "
+ for i, v := range d.Get("redundancy_group").([]interface{}) {
+ redundancyGroup := v.(map[string]interface{})
+ configSet = append(configSet, setChassisluster+"redundancy-group "+strconv.Itoa(i)+
+ " node 0 priority "+strconv.Itoa(redundancyGroup["node0_priority"].(int)))
+ configSet = append(configSet, setChassisluster+"redundancy-group "+strconv.Itoa(i)+
+ " node 1 priority "+strconv.Itoa(redundancyGroup["node1_priority"].(int)))
+ if redundancyGroup["gratuitous_arp_count"].(int) != 0 {
+ configSet = append(configSet, setChassisluster+"redundancy-group "+strconv.Itoa(i)+
+ " gratuitous-arp-count "+strconv.Itoa(redundancyGroup["gratuitous_arp_count"].(int)))
+ }
+ if redundancyGroup["hold_down_interval"].(int) != -1 {
+ configSet = append(configSet, setChassisluster+"redundancy-group "+strconv.Itoa(i)+
+ " hold-down-interval "+strconv.Itoa(redundancyGroup["hold_down_interval"].(int)))
+ }
+ for _, v2 := range redundancyGroup["interface_monitor"].([]interface{}) {
+ interfaceMonitor := v2.(map[string]interface{})
+ configSet = append(configSet, setChassisluster+"redundancy-group "+strconv.Itoa(i)+
+ " interface-monitor "+interfaceMonitor["name"].(string)+
+ " weight "+strconv.Itoa(interfaceMonitor["weight"].(int)))
+ }
+ if redundancyGroup["preempt"].(bool) {
+ configSet = append(configSet, setChassisluster+"redundancy-group "+strconv.Itoa(i)+
+ " preempt")
+ }
+ }
+ configSet = append(configSet, setChassisluster+"reth-count "+
+ strconv.Itoa(d.Get("reth_count").(int)))
+ if d.Get("config_sync_no_secondary_bootup_auto").(bool) {
+ configSet = append(configSet, setChassisluster+"configuration-synchronize no-secondary-bootup-auto")
+ }
+ if d.Get("control_link_recovery").(bool) {
+ configSet = append(configSet, setChassisluster+"control-link-recovery")
+ }
+ if v := d.Get("heartbeat_interval").(int); v != 0 {
+ configSet = append(configSet, setChassisluster+"heartbeat-interval "+
+ strconv.Itoa(v))
+ }
+ if v := d.Get("heartbeat_threshold").(int); v != 0 {
+ configSet = append(configSet, setChassisluster+"heartbeat-threshold "+
+ strconv.Itoa(v))
+ }
+
+ return sess.configSet(configSet, jnprSess)
+}
+
+func delChassisCluster(m interface{}, jnprSess *NetconfObject) error {
+ listLinesToDelete := make([]string, 0)
+ listLinesToDelete = append(listLinesToDelete, "chassis cluster")
+ listLinesToDelete = append(listLinesToDelete, "interfaces fab0")
+ listLinesToDelete = append(listLinesToDelete, "interfaces fab1")
+ sess := m.(*Session)
+ configSet := make([]string, 0)
+ for _, line := range listLinesToDelete {
+ configSet = append(configSet,
+ "delete "+line)
+ }
+
+ return sess.configSet(configSet, jnprSess)
+}
+
+func readChassisCluster(m interface{}, jnprSess *NetconfObject) (chassisClusterOptions, error) {
+ sess := m.(*Session)
+ var confRead chassisClusterOptions
+
+ chassisClusterConfig, err := sess.command("show configuration chassis cluster"+
+ " | display set relative", jnprSess)
+ if err != nil {
+ return confRead, err
+ }
+ if chassisClusterConfig != emptyWord {
+ for _, item := range strings.Split(chassisClusterConfig, "\n") {
+ if strings.Contains(item, "") {
+ continue
+ }
+ if strings.Contains(item, "") {
+ break
+ }
+ itemTrim := strings.TrimPrefix(item, setLineStart)
+ switch {
+ case strings.HasPrefix(itemTrim, "redundancy-group "):
+ itemRGTrim := strings.TrimPrefix(itemTrim, "redundancy-group ")
+ itemRGTrimSplit := strings.Split(itemRGTrim, " ")
+ number, err := strconv.Atoi(itemRGTrimSplit[0])
+ if err != nil {
+ return confRead, fmt.Errorf("failed to convert value from '%s' to integer : %w", itemRGTrimSplit[0], err)
+ }
+ if len(confRead.redundancyGroup) < number+1 {
+ confRead.redundancyGroup = append(confRead.redundancyGroup, map[string]interface{}{
+ "node0_priority": 0,
+ "node1_priority": 0,
+ "gratuitous_arp_count": 0,
+ "hold_down_interval": -1,
+ "interface_monitor": make([]map[string]interface{}, 0),
+ "preempt": false,
+ })
+ }
+ itemRGNbTrim := strings.TrimPrefix(itemRGTrim, strconv.Itoa(number)+" ")
+ switch {
+ case strings.HasPrefix(itemRGNbTrim, "node 0 priority "):
+ var err error
+ confRead.redundancyGroup[number]["node0_priority"], err =
+ strconv.Atoi(strings.TrimPrefix(itemRGNbTrim, "node 0 priority "))
+ if err != nil {
+ return confRead, fmt.Errorf("failed to convert value from '%s' to integer : %w", itemRGNbTrim, err)
+ }
+ case strings.HasPrefix(itemRGNbTrim, "node 1 priority "):
+ var err error
+ confRead.redundancyGroup[number]["node1_priority"], err =
+ strconv.Atoi(strings.TrimPrefix(itemRGNbTrim, "node 1 priority "))
+ if err != nil {
+ return confRead, fmt.Errorf("failed to convert value from '%s' to integer : %w", itemRGNbTrim, err)
+ }
+ case strings.HasPrefix(itemRGNbTrim, "gratuitous-arp-count "):
+ var err error
+ confRead.redundancyGroup[number]["gratuitous_arp_count"], err =
+ strconv.Atoi(strings.TrimPrefix(itemRGNbTrim, "gratuitous-arp-count "))
+ if err != nil {
+ return confRead, fmt.Errorf("failed to convert value from '%s' to integer : %w", itemRGNbTrim, err)
+ }
+ case strings.HasPrefix(itemRGNbTrim, "hold-down-interval "):
+ var err error
+ confRead.redundancyGroup[number]["hold_down_interval"], err =
+ strconv.Atoi(strings.TrimPrefix(itemRGNbTrim, "hold-down-interval "))
+ if err != nil {
+ return confRead, fmt.Errorf("failed to convert value from '%s' to integer : %w", itemRGNbTrim, err)
+ }
+ case strings.HasPrefix(itemRGNbTrim, "interface-monitor "):
+ name := strings.Split(strings.TrimPrefix(itemRGNbTrim, "interface-monitor "), " ")[0]
+ weight, err := strconv.Atoi(strings.TrimPrefix(itemRGNbTrim, "interface-monitor "+name+" weight "))
+ if err != nil {
+ return confRead, fmt.Errorf("failed to convert value from '%s' to integer : %w", itemRGNbTrim, err)
+ }
+ confRead.redundancyGroup[number]["interface_monitor"] = append(
+ confRead.redundancyGroup[number]["interface_monitor"].([]map[string]interface{}),
+ map[string]interface{}{
+ "name": name,
+ "weight": weight,
+ })
+ case itemRGNbTrim == preemptWord:
+ confRead.redundancyGroup[number][preemptWord] = true
+ }
+ case strings.HasPrefix(itemTrim, "reth-count "):
+ var err error
+ confRead.rethCount, err = strconv.Atoi(strings.TrimPrefix(itemTrim, "reth-count "))
+ if err != nil {
+ return confRead, fmt.Errorf("failed to convert value from '%s' to integer : %w", itemTrim, err)
+ }
+ case itemTrim == "configuration-synchronize no-secondary-bootup-auto":
+ confRead.configSyncNoSecBootAuto = true
+ case itemTrim == "control-link-recovery":
+ confRead.controlLinkRecovery = true
+ case strings.HasPrefix(itemTrim, "heartbeat-interval "):
+ var err error
+ confRead.heartbeatInterval, err = strconv.Atoi(strings.TrimPrefix(itemTrim, "heartbeat-interval "))
+ if err != nil {
+ return confRead, fmt.Errorf("failed to convert value from '%s' to integer : %w", itemTrim, err)
+ }
+ case strings.HasPrefix(itemTrim, "heartbeat-threshold "):
+ var err error
+ confRead.heartbeatThreshold, err = strconv.Atoi(strings.TrimPrefix(itemTrim, "heartbeat-threshold "))
+ if err != nil {
+ return confRead, fmt.Errorf("failed to convert value from '%s' to integer : %w", itemTrim, err)
+ }
+ }
+ }
+ }
+ fab0Config, err := sess.command("show configuration interfaces fab0"+
+ " | display set relative", jnprSess)
+ if err != nil {
+ return confRead, err
+ }
+ if fab0Config != emptyWord {
+ if len(confRead.fab0) == 0 {
+ confRead.fab0 = append(confRead.fab0, map[string]interface{}{
+ "member_interfaces": make([]string, 0),
+ "description": "",
+ })
+ }
+ for _, item := range strings.Split(fab0Config, "\n") {
+ if strings.Contains(item, "") {
+ continue
+ }
+ if strings.Contains(item, "") {
+ break
+ }
+ itemTrim := strings.TrimPrefix(item, setLineStart)
+ switch {
+ case strings.HasPrefix(itemTrim, "description "):
+ confRead.fab0[0]["description"] = strings.Trim(strings.TrimPrefix(itemTrim, "description "), "\"")
+ case strings.HasPrefix(itemTrim, "fabric-options member-interfaces "):
+ confRead.fab0[0]["member_interfaces"] = append(confRead.fab0[0]["member_interfaces"].([]string),
+ strings.TrimPrefix(itemTrim, "fabric-options member-interfaces "))
+ }
+ }
+ }
+ fab1Config, err := sess.command("show configuration interfaces fab1"+
+ " | display set relative", jnprSess)
+ if err != nil {
+ return confRead, err
+ }
+ if fab1Config != emptyWord {
+ if len(confRead.fab1) == 0 {
+ confRead.fab1 = append(confRead.fab1, map[string]interface{}{
+ "member_interfaces": make([]string, 0),
+ "description": "",
+ })
+ }
+ for _, item := range strings.Split(fab1Config, "\n") {
+ if strings.Contains(item, "") {
+ continue
+ }
+ if strings.Contains(item, "") {
+ break
+ }
+ itemTrim := strings.TrimPrefix(item, setLineStart)
+ switch {
+ case strings.HasPrefix(itemTrim, "description "):
+ confRead.fab1[0]["description"] = strings.Trim(strings.TrimPrefix(itemTrim, "description "), "\"")
+ case strings.HasPrefix(itemTrim, "fabric-options member-interfaces "):
+ confRead.fab1[0]["member_interfaces"] = append(confRead.fab1[0]["member_interfaces"].([]string),
+ strings.TrimPrefix(itemTrim, "fabric-options member-interfaces "))
+ }
+ }
+ }
+
+ return confRead, nil
+}
+
+func fillChassisCluster(d *schema.ResourceData, chassisClusterOptions chassisClusterOptions) {
+ if tfErr := d.Set("fab0", chassisClusterOptions.fab0); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("fab1", chassisClusterOptions.fab1); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("redundancy_group", chassisClusterOptions.redundancyGroup); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("reth_count", chassisClusterOptions.rethCount); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("config_sync_no_secondary_bootup_auto",
+ chassisClusterOptions.configSyncNoSecBootAuto); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("control_link_recovery", chassisClusterOptions.controlLinkRecovery); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("heartbeat_interval", chassisClusterOptions.heartbeatInterval); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("heartbeat_threshold", chassisClusterOptions.heartbeatThreshold); tfErr != nil {
+ panic(tfErr)
+ }
+}
diff --git a/junos/resource_chassis_cluster_test.go b/junos/resource_chassis_cluster_test.go
new file mode 100644
index 00000000..83a8ef60
--- /dev/null
+++ b/junos/resource_chassis_cluster_test.go
@@ -0,0 +1,130 @@
+package junos_test
+
+import (
+ "fmt"
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+)
+
+// export TESTACC_INTERFACE= for choose interface available else it's ge-0/0/3.
+// export TESTACC_INTERFACE2= for choose 2nd interface available else it's ge-0/0/4.
+func TestAccJunosCluster_basic(t *testing.T) {
+ var testaccInterface string
+ var testaccInterface2 string
+ if os.Getenv("TESTACC_INTERFACE") != "" {
+ testaccInterface = os.Getenv("TESTACC_INTERFACE")
+ } else {
+ testaccInterface = defaultInterfaceTestAcc
+ }
+ if os.Getenv("TESTACC_INTERFACE2") != "" {
+ testaccInterface2 = os.Getenv("TESTACC_INTERFACE2")
+ } else {
+ testaccInterface2 = "ge-0/0/4"
+ }
+ if os.Getenv("TESTACC_SWITCH") == "" {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ Providers: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccJunosClusterConfigCreate(testaccInterface, testaccInterface2),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("junos_chassis_cluster.testacc_cluster",
+ "fab0.#", "1"),
+ resource.TestCheckResourceAttr("junos_chassis_cluster.testacc_cluster",
+ "fab0.0.member_interfaces.#", "1"),
+ resource.TestCheckResourceAttr("junos_chassis_cluster.testacc_cluster",
+ "fab0.0.member_interfaces.0", testaccInterface),
+ resource.TestCheckResourceAttr("junos_chassis_cluster.testacc_cluster",
+ "redundancy_group.#", "2"),
+ resource.TestCheckResourceAttr("junos_chassis_cluster.testacc_cluster",
+ "redundancy_group.0.node0_priority", "100"),
+ resource.TestCheckResourceAttr("junos_chassis_cluster.testacc_cluster",
+ "redundancy_group.1.interface_monitor.#", "1"),
+ resource.TestCheckResourceAttr("junos_chassis_cluster.testacc_cluster",
+ "redundancy_group.1.interface_monitor.0.name", testaccInterface2),
+ resource.TestCheckResourceAttr("junos_chassis_cluster.testacc_cluster",
+ "reth_count", "2"),
+ ),
+ },
+ {
+ Config: testAccJunosClusterConfigUpdate(testaccInterface, testaccInterface2),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("junos_chassis_cluster.testacc_cluster",
+ "redundancy_group.#", "2"),
+ resource.TestCheckResourceAttr("junos_chassis_cluster.testacc_cluster",
+ "redundancy_group.1.node0_priority", "100"),
+ resource.TestCheckResourceAttr("junos_chassis_cluster.testacc_cluster",
+ "reth_count", "3"),
+ ),
+ },
+ {
+ ResourceName: "junos_chassis_cluster.testacc_cluster",
+ ImportState: true,
+ ImportStateVerify: true,
+ },
+ },
+ })
+ }
+}
+
+func testAccJunosClusterConfigCreate(interFace, interFace2 string) string {
+ return fmt.Sprintf(`
+resource "junos_interface_physical" "testacc_cluster_int2" {
+ name = "` + interFace2 + `"
+ description = "testacc_cluster_int2"
+ gigether_opts {
+ redundant_parent = "reth0"
+ }
+}
+resource "junos_chassis_cluster" "testacc_cluster" {
+ fab0 {
+ member_interfaces = ["` + interFace + `"]
+ }
+ redundancy_group {
+ node0_priority = 100
+ node1_priority = 99
+ }
+ redundancy_group {
+ node0_priority = 98
+ node1_priority = 97
+ interface_monitor {
+ name = junos_interface_physical.testacc_cluster_int2.name
+ weight = 255
+ }
+ }
+ reth_count = 2
+}
+`)
+}
+func testAccJunosClusterConfigUpdate(interFace, interFace2 string) string {
+ return fmt.Sprintf(`
+resource "junos_interface_physical" "testacc_cluster_int2" {
+ name = "` + interFace2 + `"
+ description = "testacc_cluster_int2"
+ gigether_opts {
+ redundant_parent = "reth0"
+ }
+}
+resource "junos_chassis_cluster" "testacc_cluster" {
+ fab0 {
+ member_interfaces = ["` + interFace + `"]
+ }
+ redundancy_group {
+ node0_priority = 100
+ node1_priority = 99
+ }
+ redundancy_group {
+ node0_priority = 100
+ node1_priority = 99
+ interface_monitor {
+ name = junos_interface_physical.testacc_cluster_int2.name
+ weight = 255
+ }
+ }
+ reth_count = 3
+}
+`)
+}
diff --git a/junos/resource_firewall_filter.go b/junos/resource_firewall_filter.go
index d851080c..56009688 100644
--- a/junos/resource_firewall_filter.go
+++ b/junos/resource_firewall_filter.go
@@ -31,7 +31,7 @@ func resourceFirewallFilter() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"family": {
Type: schema.TypeString,
@@ -52,12 +52,12 @@ func resourceFirewallFilter() *schema.Resource {
"name": {
Type: schema.TypeString,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"filter": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"from": {
Type: schema.TypeList,
@@ -236,7 +236,7 @@ func resourceFirewallFilter() *schema.Resource {
"policer": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"port_mirror": {
Type: schema.TypeBool,
@@ -270,6 +270,14 @@ func resourceFirewallFilter() *schema.Resource {
func resourceFirewallFilterCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setFirewallFilter(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string) + idSeparator + d.Get("family").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -465,11 +473,7 @@ func setFirewallFilter(d *schema.ResourceData, m interface{}, jnprSess *NetconfO
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readFirewallFilter(filter, family string, m interface{}, jnprSess *NetconfObject) (filterOptions, error) {
sess := m.(*Session)
@@ -528,11 +532,8 @@ func delFirewallFilter(filter, family string, m interface{}, jnprSess *NetconfOb
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete firewall family "+family+" filter "+filter)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillFirewallFilterData(d *schema.ResourceData, filterOptions filterOptions) {
if tfErr := d.Set("name", filterOptions.name); tfErr != nil {
diff --git a/junos/resource_firewall_policer.go b/junos/resource_firewall_policer.go
index b68f6ff4..11e6c11d 100644
--- a/junos/resource_firewall_policer.go
+++ b/junos/resource_firewall_policer.go
@@ -32,7 +32,7 @@ func resourceFirewallPolicer() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"filter_specific": {
Type: schema.TypeBool,
@@ -97,6 +97,14 @@ func resourceFirewallPolicer() *schema.Resource {
func resourceFirewallPolicerCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setFirewallPolicer(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -304,11 +312,7 @@ func setFirewallPolicer(d *schema.ResourceData, m interface{}, jnprSess *Netconf
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readFirewallPolicer(policer string, m interface{}, jnprSess *NetconfObject) (policerOptions, error) {
sess := m.(*Session)
@@ -390,11 +394,8 @@ func delFirewallPolicer(policer string, m interface{}, jnprSess *NetconfObject)
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete firewall policer "+policer)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillFirewallPolicerData(d *schema.ResourceData, policerOptions policerOptions) {
if tfErr := d.Set("name", policerOptions.name); tfErr != nil {
diff --git a/junos/resource_group_dual_system.go b/junos/resource_group_dual_system.go
new file mode 100644
index 00000000..5552168c
--- /dev/null
+++ b/junos/resource_group_dual_system.go
@@ -0,0 +1,549 @@
+package junos
+
+import (
+ "context"
+ "fmt"
+ "strings"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
+)
+
+type groupDualSystemOptions struct {
+ applyGroups bool
+ name string
+ interfaceFxp0 []map[string]interface{}
+ routingOptions []map[string]interface{}
+ security []map[string]interface{}
+ system []map[string]interface{}
+}
+
+func resourceGroupDualSystem() *schema.Resource {
+ return &schema.Resource{
+ CreateContext: resourceGroupDualSystemCreate,
+ ReadContext: resourceGroupDualSystemRead,
+ UpdateContext: resourceGroupDualSystemUpdate,
+ DeleteContext: resourceGroupDualSystemDelete,
+ Importer: &schema.ResourceImporter{
+ State: resourceGroupDualSystemImport,
+ },
+ Schema: map[string]*schema.Schema{
+ "name": {
+ Type: schema.TypeString,
+ ForceNew: true,
+ Required: true,
+ ValidateFunc: validation.StringInSlice([]string{"node0", "node1", "re0", "re1"}, false),
+ },
+ "apply_groups": {
+ Type: schema.TypeBool,
+ Default: true,
+ Optional: true,
+ },
+ "interface_fxp0": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "description": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "family_inet_address": {
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "cidr_ip": {
+ Type: schema.TypeString,
+ Required: true,
+ ValidateDiagFunc: validateIPMaskFunc(),
+ },
+ "master_only": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "routing_options": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "static_route": {
+ Type: schema.TypeList,
+ Required: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "destination": {
+ Type: schema.TypeString,
+ Required: true,
+ ValidateFunc: validation.IsCIDRNetwork(0, 128),
+ },
+ "next_hop": {
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "security": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "log_source_address": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ },
+ },
+ },
+ "system": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "host_name": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "backup_router_address": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "backup_router_destination": {
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
+func resourceGroupDualSystemCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setGroupDualSystem(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ defer sess.closeSession(jnprSess)
+ sess.configLock(jnprSess)
+ groupDualSystemExists, err := checkGroupDualSystemExists(d.Get("name").(string), m, jnprSess)
+ if err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ if groupDualSystemExists {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(fmt.Errorf("group %v already exists", d.Get("name").(string)))
+ }
+
+ if err := setGroupDualSystem(d, m, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ var diagWarns diag.Diagnostics
+ warns, err := sess.commitConf("create resource junos_group_dual_system", jnprSess)
+ appendDiagWarns(&diagWarns, warns)
+ if err != nil {
+ sess.configClear(jnprSess)
+
+ return append(diagWarns, diag.FromErr(err)...)
+ }
+ groupDualSystemExists, err = checkGroupDualSystemExists(d.Get("name").(string), m, jnprSess)
+ if err != nil {
+ return append(diagWarns, diag.FromErr(err)...)
+ }
+ if groupDualSystemExists {
+ d.SetId(d.Get("name").(string))
+ } else {
+ return append(diagWarns, diag.FromErr(fmt.Errorf("group %v not exists after commit "+
+ "=> check your config", d.Get("name").(string)))...)
+ }
+
+ return append(diagWarns, resourceGroupDualSystemReadWJnprSess(d, m, jnprSess)...)
+}
+func resourceGroupDualSystemRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ sess := m.(*Session)
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ defer sess.closeSession(jnprSess)
+
+ return resourceGroupDualSystemReadWJnprSess(d, m, jnprSess)
+}
+func resourceGroupDualSystemReadWJnprSess(
+ d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) diag.Diagnostics {
+ mutex.Lock()
+ groupDualSystemOpts, err := readGroupDualSystem(d.Get("name").(string), m, jnprSess)
+ mutex.Unlock()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ if groupDualSystemOpts.name == "" {
+ d.SetId("")
+ } else {
+ fillGroupDualSystemData(d, groupDualSystemOpts)
+ }
+
+ return nil
+}
+func resourceGroupDualSystemUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ d.Partial(true)
+ sess := m.(*Session)
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ defer sess.closeSession(jnprSess)
+ sess.configLock(jnprSess)
+ if err := delGroupDualSystem(d.Get("name").(string), m, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ if strings.HasPrefix(d.Get("name").(string), "node") {
+ if err := sess.configSet([]string{"delete apply-groups \"${node}\""}, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ } else if err := sess.configSet([]string{"delete apply-groups " + d.Get("name").(string)}, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ if err := setGroupDualSystem(d, m, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ var diagWarns diag.Diagnostics
+ warns, err := sess.commitConf("update resource junos_group_dual_system", jnprSess)
+ appendDiagWarns(&diagWarns, warns)
+ if err != nil {
+ sess.configClear(jnprSess)
+
+ return append(diagWarns, diag.FromErr(err)...)
+ }
+ d.Partial(false)
+
+ return append(diagWarns, resourceGroupDualSystemReadWJnprSess(d, m, jnprSess)...)
+}
+func resourceGroupDualSystemDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ sess := m.(*Session)
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ defer sess.closeSession(jnprSess)
+ sess.configLock(jnprSess)
+ if err := delGroupDualSystem(d.Get("name").(string), m, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ if strings.HasPrefix(d.Get("name").(string), "node") {
+ if err := sess.configSet([]string{"delete apply-groups \"${node}\""}, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ } else if err := sess.configSet([]string{"delete apply-groups " + d.Get("name").(string)}, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ var diagWarns diag.Diagnostics
+ warns, err := sess.commitConf("delete resource junos_group_dual_system", jnprSess)
+ appendDiagWarns(&diagWarns, warns)
+ if err != nil {
+ sess.configClear(jnprSess)
+
+ return append(diagWarns, diag.FromErr(err)...)
+ }
+
+ return diagWarns
+}
+func resourceGroupDualSystemImport(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) {
+ sess := m.(*Session)
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return nil, err
+ }
+ defer sess.closeSession(jnprSess)
+ result := make([]*schema.ResourceData, 1)
+
+ if !stringInSlice(d.Id(), []string{"node0", "node1", "re0", "re1"}) {
+ return nil, fmt.Errorf("invalid group id '%v' (id must be )", d.Id())
+ }
+ groupDualSystemExists, err := checkGroupDualSystemExists(d.Id(), m, jnprSess)
+ if err != nil {
+ return nil, err
+ }
+ if !groupDualSystemExists {
+ return nil, fmt.Errorf("don't find group with id '%v' (id must be )", d.Id())
+ }
+ groupDualSystemOptions, err := readGroupDualSystem(d.Id(), m, jnprSess)
+ if err != nil {
+ return nil, err
+ }
+ fillGroupDualSystemData(d, groupDualSystemOptions)
+
+ result[0] = d
+
+ return result, nil
+}
+
+func checkGroupDualSystemExists(name string, m interface{}, jnprSess *NetconfObject) (bool, error) {
+ sess := m.(*Session)
+ groupDualSystemConfig, err := sess.command("show configuration groups "+name+" | display set", jnprSess)
+ if err != nil {
+ return false, err
+ }
+ if groupDualSystemConfig == emptyWord {
+ return false, nil
+ }
+
+ return true, nil
+}
+func setGroupDualSystem(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
+ sess := m.(*Session)
+ configSet := make([]string, 0)
+
+ if d.Get("apply_groups").(bool) {
+ if strings.HasPrefix(d.Get("name").(string), "node") {
+ configSet = append(configSet, "set apply-groups \"${node}\"")
+ } else {
+ configSet = append(configSet, "set apply-groups "+d.Get("name").(string))
+ }
+ }
+ setPrefix := "set groups " + d.Get("name").(string) + " "
+ for _, v := range d.Get("interface_fxp0").([]interface{}) {
+ if v == nil {
+ return fmt.Errorf("interface_fxp0 block is empty")
+ }
+ interfaceFxp0 := v.(map[string]interface{})
+ if v2 := interfaceFxp0["description"].(string); v2 != "" {
+ configSet = append(configSet, setPrefix+"interfaces fxp0 description \""+v2+"\"")
+ }
+ for _, v2 := range interfaceFxp0["family_inet_address"].([]interface{}) {
+ familyInetAddress := v2.(map[string]interface{})
+ configSet = append(configSet, setPrefix+"interfaces fxp0 unit 0 family inet address "+
+ familyInetAddress["cidr_ip"].(string))
+ if familyInetAddress["master_only"].(bool) {
+ configSet = append(configSet, setPrefix+"interfaces fxp0 unit 0 family inet address "+
+ familyInetAddress["cidr_ip"].(string)+" master-only")
+ }
+ }
+ }
+ for _, v := range d.Get("routing_options").([]interface{}) {
+ routingOptions := v.(map[string]interface{})
+ for _, v2 := range routingOptions["static_route"].([]interface{}) {
+ staticRoute := v2.(map[string]interface{})
+ for _, v3 := range staticRoute["next_hop"].([]interface{}) {
+ configSet = append(configSet, setPrefix+"routing-options static route "+
+ staticRoute["destination"].(string)+" next-hop "+v3.(string))
+ }
+ }
+ }
+ for _, v := range d.Get("security").([]interface{}) {
+ security := v.(map[string]interface{})
+ if v2 := security["log_source_address"].(string); v2 != "" {
+ configSet = append(configSet, setPrefix+"security log source-address "+v2)
+ }
+ }
+ for _, v := range d.Get("system").([]interface{}) {
+ if v == nil {
+ return fmt.Errorf("system block is empty")
+ }
+ system := v.(map[string]interface{})
+ if v2 := system["host_name"].(string); v2 != "" {
+ configSet = append(configSet, setPrefix+" system host-name \""+v2+"\"")
+ }
+ if v2 := system["backup_router_address"].(string); v2 != "" {
+ configSet = append(configSet, setPrefix+" system backup-router "+v2)
+ }
+ for _, v2 := range system["backup_router_destination"].([]interface{}) {
+ configSet = append(configSet, setPrefix+" system backup-router destination "+v2.(string))
+ }
+ }
+
+ return sess.configSet(configSet, jnprSess)
+}
+func readGroupDualSystem(group string, m interface{}, jnprSess *NetconfObject) (groupDualSystemOptions, error) {
+ sess := m.(*Session)
+ var confRead groupDualSystemOptions
+
+ groupDualSystemConfig, err := sess.command("show configuration groups "+group+" | display set relative", jnprSess)
+ if err != nil {
+ return confRead, err
+ }
+ if groupDualSystemConfig != emptyWord {
+ confRead.name = group
+ for _, item := range strings.Split(groupDualSystemConfig, "\n") {
+ if strings.Contains(item, "") {
+ continue
+ }
+ if strings.Contains(item, "") {
+ break
+ }
+ itemTrim := strings.TrimPrefix(item, setLineStart)
+ switch {
+ case strings.HasPrefix(itemTrim, "interfaces fxp0 "):
+ if len(confRead.interfaceFxp0) == 0 {
+ confRead.interfaceFxp0 = append(confRead.interfaceFxp0, map[string]interface{}{
+ "description": "",
+ "family_inet_address": make([]map[string]interface{}, 0),
+ })
+ }
+ switch {
+ case strings.HasPrefix(itemTrim, "interfaces fxp0 description "):
+ confRead.interfaceFxp0[0]["description"] = strings.TrimPrefix(itemTrim, "interfaces fxp0 description ")
+ case strings.HasPrefix(itemTrim, "interfaces fxp0 unit 0 family inet address "):
+ if strings.HasSuffix(itemTrim, "master-only") {
+ confRead.interfaceFxp0[0]["family_inet_address"] = append(
+ confRead.interfaceFxp0[0]["family_inet_address"].([]map[string]interface{}), map[string]interface{}{
+ "cidr_ip": strings.TrimSuffix(strings.TrimPrefix(
+ itemTrim, "interfaces fxp0 unit 0 family inet address "), " master-only"),
+ "master_only": true,
+ })
+ } else {
+ confRead.interfaceFxp0[0]["family_inet_address"] = append(
+ confRead.interfaceFxp0[0]["family_inet_address"].([]map[string]interface{}), map[string]interface{}{
+ "cidr_ip": strings.TrimPrefix(itemTrim, "interfaces fxp0 unit 0 family inet address "),
+ "master_only": false,
+ })
+ }
+ }
+ case strings.HasPrefix(itemTrim, "routing-options static route "):
+ if len(confRead.routingOptions) == 0 {
+ confRead.routingOptions = append(confRead.routingOptions, map[string]interface{}{
+ "static_route": make([]map[string]interface{}, 0),
+ })
+ }
+ routeTrim := strings.TrimPrefix(itemTrim, "routing-options static route ")
+ routeTrimSplit := strings.Split(routeTrim, " ")
+ destOptions := map[string]interface{}{
+ "destination": routeTrimSplit[0],
+ "next_hop": make([]string, 0),
+ }
+ destOptions, confRead.routingOptions[0]["static_route"] = copyAndRemoveItemMapList(
+ "destination", false, destOptions, confRead.routingOptions[0]["static_route"].([]map[string]interface{}))
+ if strings.HasPrefix(routeTrim, routeTrimSplit[0]+" next-hop ") {
+ destOptions["next_hop"] = append(destOptions["next_hop"].([]string),
+ strings.TrimPrefix(routeTrim, routeTrimSplit[0]+" next-hop "))
+ }
+ confRead.routingOptions[0]["static_route"] = append(
+ confRead.routingOptions[0]["static_route"].([]map[string]interface{}), destOptions)
+ case strings.HasPrefix(itemTrim, "security"):
+ if len(confRead.security) == 0 {
+ confRead.security = append(confRead.security, map[string]interface{}{
+ "log_source_address": "",
+ })
+ }
+ if strings.HasPrefix(itemTrim, "security log source-address ") {
+ confRead.security[0]["log_source_address"] = strings.TrimPrefix(
+ itemTrim, "security log source-address ")
+ }
+ case strings.HasPrefix(itemTrim, "system"):
+ if len(confRead.system) == 0 {
+ confRead.system = append(confRead.system, map[string]interface{}{
+ "host_name": "",
+ "backup_router_address": "",
+ "backup_router_destination": make([]string, 0),
+ })
+ }
+ switch {
+ case strings.HasPrefix(itemTrim, "system host-name "):
+ confRead.system[0]["host_name"] = strings.Trim(strings.TrimPrefix(itemTrim, "system host-name "), "\"")
+ case strings.HasPrefix(itemTrim, "system backup-router destination "):
+ confRead.system[0]["backup_router_destination"] = append(
+ confRead.system[0]["backup_router_destination"].([]string),
+ strings.TrimPrefix(itemTrim, "system backup-router destination "))
+ case strings.HasPrefix(itemTrim, "system backup-router "):
+ confRead.system[0]["backup_router_address"] = strings.TrimPrefix(itemTrim, "system backup-router ")
+ }
+ }
+ }
+ }
+ applyGroupsConfig, err := sess.command("show configuration apply-groups | display set relative", jnprSess)
+ if err != nil {
+ return confRead, err
+ }
+ if applyGroupsConfig != emptyWord {
+ confRead.name = group
+ for _, item := range strings.Split(applyGroupsConfig, "\n") {
+ if strings.Contains(item, "") {
+ continue
+ }
+ if strings.Contains(item, "") {
+ break
+ }
+ switch {
+ case item == "set "+confRead.name+" ":
+ confRead.applyGroups = true
+ case item == "set \"${node}\" " && strings.HasPrefix(confRead.name, "node"):
+ confRead.applyGroups = true
+ }
+ }
+ }
+
+ return confRead, nil
+}
+
+func delGroupDualSystem(group string, m interface{}, jnprSess *NetconfObject) error {
+ sess := m.(*Session)
+ configSet := make([]string, 0, 1)
+ configSet = append(configSet, "delete groups "+group)
+
+ return sess.configSet(configSet, jnprSess)
+}
+func fillGroupDualSystemData(d *schema.ResourceData, groupDualSystemOptions groupDualSystemOptions) {
+ if tfErr := d.Set("name", groupDualSystemOptions.name); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("apply_groups", groupDualSystemOptions.applyGroups); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("interface_fxp0", groupDualSystemOptions.interfaceFxp0); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("routing_options", groupDualSystemOptions.routingOptions); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("security", groupDualSystemOptions.security); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("system", groupDualSystemOptions.system); tfErr != nil {
+ panic(tfErr)
+ }
+}
diff --git a/junos/resource_group_dual_system_test.go b/junos/resource_group_dual_system_test.go
new file mode 100644
index 00000000..3ab436f5
--- /dev/null
+++ b/junos/resource_group_dual_system_test.go
@@ -0,0 +1,118 @@
+package junos_test
+
+import (
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+)
+
+func TestAccJunosGroupDualSystem_basic(t *testing.T) {
+ if os.Getenv("TESTACC_SRX") != "" {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ Providers: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccJunosGroupDualSystemConfigCreate(),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("junos_group_dual_system.testacc_node0",
+ "apply_groups", "true"),
+ ),
+ },
+ {
+ Config: testAccJunosGroupDualSystemConfigUpdate(),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("junos_group_dual_system.testacc_node0",
+ "interface_fxp0.#", "1"),
+ resource.TestCheckResourceAttr("junos_group_dual_system.testacc_node0",
+ "interface_fxp0.0.family_inet_address.#", "2"),
+ resource.TestCheckResourceAttr("junos_group_dual_system.testacc_node0",
+ "system.#", "1"),
+ resource.TestCheckResourceAttr("junos_group_dual_system.testacc_node0",
+ "system.0.backup_router_destination.#", "2"),
+ resource.TestCheckResourceAttr("junos_group_dual_system.testacc_node0",
+ "system.#", "1"),
+ resource.TestCheckResourceAttr("junos_group_dual_system.testacc_node0",
+ "system.0.backup_router_destination.1", "192.0.2.0/26"),
+ ),
+ },
+ {
+ ResourceName: "junos_group_dual_system.testacc_node0",
+ ImportState: true,
+ ImportStateVerify: true,
+ },
+ },
+ })
+ }
+}
+
+func testAccJunosGroupDualSystemConfigCreate() string {
+ return `
+resource "junos_group_dual_system" "testacc_node0" {
+ name = "node0"
+ interface_fxp0 {
+ description = "test_"
+ family_inet_address {
+ cidr_ip = "192.0.2.193/26"
+ }
+ }
+ routing_options {
+ static_route {
+ destination = "192.0.2.0/26"
+ next_hop = ["192.0.2.254"]
+ }
+ static_route {
+ destination = "192.0.2.64/26"
+ next_hop = ["192.0.2.254"]
+ }
+ }
+ security {
+ log_source_address = "192.0.2.128"
+ }
+ system {
+ host_name = "test_node"
+ backup_router_address = "192.0.2.254"
+ backup_router_destination = [
+ "192.0.2.0/26",
+ ]
+ }
+}
+`
+}
+func testAccJunosGroupDualSystemConfigUpdate() string {
+ return `
+resource "junos_group_dual_system" "testacc_node0" {
+ name = "node0"
+ apply_groups = false
+ interface_fxp0 {
+ description = "test_"
+ family_inet_address {
+ cidr_ip = "192.0.2.193/26"
+ }
+ family_inet_address {
+ cidr_ip = "192.0.2.194/26"
+ master_only = true
+ }
+ }
+ routing_options {
+ static_route {
+ destination = "192.0.2.0/26"
+ next_hop = ["192.0.2.254"]
+ }
+ }
+ security {
+ log_source_address = "192.0.2.128"
+ }
+ system {
+ host_name = "test_node"
+ backup_router_address = "192.0.2.254"
+ backup_router_destination = [
+ "192.0.2.64/26",
+ "192.0.2.0/26",
+
+ ]
+ }
+}
+`
+}
diff --git a/junos/resource_interface.go b/junos/resource_interface.go
index 54095732..5964f4d1 100644
--- a/junos/resource_interface.go
+++ b/junos/resource_interface.go
@@ -322,22 +322,22 @@ func resourceInterface() *schema.Resource {
"inet_filter_input": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"inet_filter_output": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"inet6_filter_input": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"inet6_filter_output": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"inet_rpf_check": {
Type: schema.TypeList,
@@ -418,12 +418,12 @@ func resourceInterface() *schema.Resource {
"security_zone": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"routing_instance": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
},
}
@@ -431,6 +431,26 @@ func resourceInterface() *schema.Resource {
func resourceInterfaceCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if sess.junosGroupIntDel != "" {
+ if err := delInterfaceElement("apply-groups "+sess.junosGroupIntDel, d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ } else {
+ if err := delInterfaceElement("disable", d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ if err := delInterfaceElement("description", d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ }
+ if err := setInterface(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -1025,12 +1045,14 @@ func setInterface(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject
oldAE = oldAEtf.(string)
}
}
- aggregatedCount, err := aggregatedCountSearchMax(d.Get("ether802_3ad").(string), oldAE,
- d.Get("name").(string), m, jnprSess)
- if err != nil {
- return err
+ if jnprSess != nil {
+ aggregatedCount, err := aggregatedCountSearchMax(d.Get("ether802_3ad").(string), oldAE,
+ d.Get("name").(string), m, jnprSess)
+ if err != nil {
+ return err
+ }
+ configSet = append(configSet, "set chassis aggregated-devices ethernet device-count "+aggregatedCount)
}
- configSet = append(configSet, "set chassis aggregated-devices ethernet device-count "+aggregatedCount)
}
if d.Get("trunk").(bool) {
configSet = append(configSet, setPrefix+"unit 0 family ethernet-switching interface-mode trunk")
@@ -1063,7 +1085,7 @@ func setInterface(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject
configSet = append(configSet, setPrefix+
"aggregated-ether-options minimum-links "+strconv.Itoa(d.Get("ae_minimum_links").(int)))
}
- if checkCompatibilitySecurity(jnprSess) && d.Get("security_zone").(string) != "" {
+ if d.Get("security_zone").(string) != "" {
configSet = append(configSet, "set security zones security-zone "+
d.Get("security_zone").(string)+" interfaces "+d.Get("name").(string))
}
@@ -1072,11 +1094,7 @@ func setInterface(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject
" interface "+d.Get("name").(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readInterface(interFace string, m interface{}, jnprSess *NetconfObject) (interfaceOptions, error) {
sess := m.(*Session)
@@ -1381,11 +1399,8 @@ func delInterfaceElement(element string, d *schema.ResourceData, m interface{},
return fmt.Errorf("the name %s contains too dots", d.Get("name").(string))
}
configSet = append(configSet, "delete interfaces "+setName+" "+element)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func delInterfaceOpts(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
@@ -1415,33 +1430,25 @@ func delInterfaceOpts(d *schema.ResourceData, m interface{}, jnprSess *NetconfOb
delPrefix+"unit 0 family ethernet-switching interface-mode",
delPrefix+"unit 0 family ethernet-switching vlan members",
delPrefix+"native-vlan-id",
- delPrefix+"aggregated-ether-options")
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
+ delPrefix+"aggregated-ether-options",
+ )
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func delZoneInterface(zone string, d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security zones security-zone "+zone+" interfaces "+d.Get("name").(string))
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func delRoutingInstanceInterface(instance string, d *schema.ResourceData,
m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete routing-instances "+instance+" interface "+d.Get("name").(string))
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillInterfaceData(d *schema.ResourceData, interfaceOpt interfaceOptions) {
@@ -1538,7 +1545,7 @@ func fillFamilyInetAddressOld(item string, inetAddress []map[string]interface{},
vrrpGroup := genVRRPGroupOld(family)
vrrpID, err := strconv.Atoi(addressConfig[2])
if err != nil {
- return inetAddress, nil
+ return inetAddress, fmt.Errorf("failed to convert value from '%s' to integer : %w", itemTrim, err)
}
itemTrimVrrp := strings.TrimPrefix(itemTrim, "vrrp-group "+strconv.Itoa(vrrpID)+" ")
if strings.HasPrefix(itemTrim, "vrrp-inet6-group ") {
diff --git a/junos/resource_interface_logical.go b/junos/resource_interface_logical.go
index a4a5a2a7..667a6055 100644
--- a/junos/resource_interface_logical.go
+++ b/junos/resource_interface_logical.go
@@ -14,12 +14,14 @@ import (
)
type interfaceLogicalOptions struct {
- vlanID int
- description string
- routingInstance string
- securityZone string
- familyInet []map[string]interface{}
- familyInet6 []map[string]interface{}
+ vlanID int
+ description string
+ routingInstance string
+ securityZone string
+ securityInboundProtocols []string
+ securityInboundServices []string
+ familyInet []map[string]interface{}
+ familyInet6 []map[string]interface{}
}
func resourceInterfaceLogical() *schema.Resource {
@@ -173,12 +175,12 @@ func resourceInterfaceLogical() *schema.Resource {
"filter_input": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"filter_output": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"mtu": {
Type: schema.TypeInt,
@@ -320,12 +322,12 @@ func resourceInterfaceLogical() *schema.Resource {
"filter_input": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"filter_output": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"mtu": {
Type: schema.TypeInt,
@@ -355,12 +357,24 @@ func resourceInterfaceLogical() *schema.Resource {
"routing_instance": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
+ },
+ "security_inbound_protocols": {
+ Type: schema.TypeList,
+ Optional: true,
+ RequiredWith: []string{"security_zone"},
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ "security_inbound_services": {
+ Type: schema.TypeList,
+ Optional: true,
+ RequiredWith: []string{"security_zone"},
+ Elem: &schema.Schema{Type: schema.TypeString},
},
"security_zone": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"vlan_id": {
Type: schema.TypeInt,
@@ -374,6 +388,17 @@ func resourceInterfaceLogical() *schema.Resource {
func resourceInterfaceLogicalCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := delInterfaceNC(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ if err := setInterfaceLogical(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -556,6 +581,12 @@ func resourceInterfaceLogicalUpdate(ctx context.Context, d *schema.ResourceData,
return diag.FromErr(err)
}
}
+ } else if v := d.Get("security_zone").(string); v != "" {
+ if err := delZoneInterfaceLogical(v, d, m, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
}
if d.HasChange("routing_instance") {
oRoutingInstance, nRoutingInstance := d.GetChange("routing_instance")
@@ -803,9 +834,19 @@ func setInterfaceLogical(d *schema.ResourceData, m interface{}, jnprSess *Netcon
configSet = append(configSet, "set routing-instances "+d.Get("routing_instance").(string)+
" interface "+d.Get("name").(string))
}
- if checkCompatibilitySecurity(jnprSess) && d.Get("security_zone").(string) != "" {
+ if d.Get("security_zone").(string) != "" {
configSet = append(configSet, "set security zones security-zone "+
d.Get("security_zone").(string)+" interfaces "+d.Get("name").(string))
+ for _, v := range d.Get("security_inbound_protocols").([]interface{}) {
+ configSet = append(configSet, "set security zones security-zone "+
+ d.Get("security_zone").(string)+" interfaces "+d.Get("name").(string)+
+ " host-inbound-traffic protocols "+v.(string))
+ }
+ for _, v := range d.Get("security_inbound_services").([]interface{}) {
+ configSet = append(configSet, "set security zones security-zone "+
+ d.Get("security_zone").(string)+" interfaces "+d.Get("name").(string)+
+ " host-inbound-traffic system-services "+v.(string))
+ }
}
if d.Get("vlan_id").(int) != 0 {
configSet = append(configSet, setPrefix+"vlan-id "+strconv.Itoa(d.Get("vlan_id").(int)))
@@ -813,11 +854,7 @@ func setInterfaceLogical(d *schema.ResourceData, m interface{}, jnprSess *Netcon
configSet = append(configSet, setPrefix+"vlan-id "+intCut[1])
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readInterfaceLogical(interFace string, m interface{}, jnprSess *NetconfObject) (interfaceLogicalOptions, error) {
sess := m.(*Session)
@@ -962,12 +999,15 @@ func readInterfaceLogical(interFace string, m interface{}, jnprSess *NetconfObje
if err != nil {
return confRead, err
}
- regexpInts := regexp.MustCompile(`set security-zone \S+ interfaces ` + interFace + `$`)
+ regexpInts := regexp.MustCompile(`set security-zone \S+ interfaces ` + interFace + `( host-inbound-traffic .*)?$`)
for _, item := range strings.Split(zonesConfig, "\n") {
intMatch := regexpInts.MatchString(item)
if intMatch {
- confRead.securityZone = strings.TrimPrefix(strings.TrimSuffix(item, " interfaces "+interFace),
- "set security-zone ")
+ itemTrimSplit := strings.Split(strings.TrimPrefix(item, "set security-zone "), " ")
+ confRead.securityZone = itemTrimSplit[0]
+ if err := readInterfaceLogicalSecurityInboundTraffic(interFace, &confRead, m, jnprSess); err != nil {
+ return confRead, err
+ }
break
}
@@ -976,6 +1016,39 @@ func readInterfaceLogical(interFace string, m interface{}, jnprSess *NetconfObje
return confRead, nil
}
+func readInterfaceLogicalSecurityInboundTraffic(interFace string, confRead *interfaceLogicalOptions,
+ m interface{}, jnprSess *NetconfObject) error {
+ sess := m.(*Session)
+
+ intConfig, err := sess.command("show configuration security zones security-zone "+confRead.securityZone+
+ " interfaces "+interFace+" | display set relative", jnprSess)
+ if err != nil {
+ return err
+ }
+
+ if intConfig != emptyWord {
+ for _, item := range strings.Split(intConfig, "\n") {
+ if strings.Contains(item, "") {
+ continue
+ }
+ if strings.Contains(item, "") {
+ break
+ }
+ itemTrim := strings.TrimPrefix(item, setLineStart)
+ switch {
+ case strings.HasPrefix(itemTrim, "host-inbound-traffic protocols "):
+ confRead.securityInboundProtocols = append(confRead.securityInboundProtocols,
+ strings.TrimPrefix(itemTrim, "host-inbound-traffic protocols "))
+ case strings.HasPrefix(itemTrim, "host-inbound-traffic system-services "):
+ confRead.securityInboundServices = append(confRead.securityInboundServices,
+ strings.TrimPrefix(itemTrim, "host-inbound-traffic system-services "))
+ }
+ }
+ }
+
+ return nil
+}
+
func delInterfaceLogical(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
if err := sess.configSet([]string{"delete interfaces " + d.Get("name").(string)}, jnprSess); err != nil {
@@ -1009,34 +1082,26 @@ func delInterfaceLogicalOpts(d *schema.ResourceData, m interface{}, jnprSess *Ne
configSet := make([]string, 0, 1)
delPrefix := "delete interfaces " + d.Get("name").(string) + " "
configSet = append(configSet,
+ delPrefix+"description",
delPrefix+"family inet",
delPrefix+"family inet6")
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func delZoneInterfaceLogical(zone string, d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security zones security-zone "+zone+" interfaces "+d.Get("name").(string))
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func delRoutingInstanceInterfaceLogical(instance string, d *schema.ResourceData,
m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete routing-instances "+instance+" interface "+d.Get("name").(string))
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillInterfaceLogicalData(d *schema.ResourceData, interfaceLogicalOpt interfaceLogicalOptions) {
@@ -1052,6 +1117,12 @@ func fillInterfaceLogicalData(d *schema.ResourceData, interfaceLogicalOpt interf
if tfErr := d.Set("routing_instance", interfaceLogicalOpt.routingInstance); tfErr != nil {
panic(tfErr)
}
+ if tfErr := d.Set("security_inbound_protocols", interfaceLogicalOpt.securityInboundProtocols); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("security_inbound_services", interfaceLogicalOpt.securityInboundServices); tfErr != nil {
+ panic(tfErr)
+ }
if tfErr := d.Set("security_zone", interfaceLogicalOpt.securityZone); tfErr != nil {
panic(tfErr)
}
@@ -1080,7 +1151,7 @@ func fillFamilyInetAddress(item string, inetAddress []map[string]interface{},
vrrpGroup := genVRRPGroup(family)
vrrpID, err := strconv.Atoi(addressConfig[2])
if err != nil {
- return inetAddress, nil
+ return inetAddress, fmt.Errorf("failed to convert value from '%s' to integer : %w", itemTrim, err)
}
itemTrimVrrp := strings.TrimPrefix(itemTrim, "vrrp-group "+strconv.Itoa(vrrpID)+" ")
if strings.HasPrefix(itemTrim, "vrrp-inet6-group ") {
diff --git a/junos/resource_interface_logical_test.go b/junos/resource_interface_logical_test.go
index 9c3f6fe0..f79f6ef2 100644
--- a/junos/resource_interface_logical_test.go
+++ b/junos/resource_interface_logical_test.go
@@ -219,10 +219,12 @@ resource junos_interface_physical testacc_interface_logical_phy {
vlan_tagging = true
}
resource junos_interface_logical testacc_interface_logical {
- name = "${junos_interface_physical.testacc_interface_logical_phy.name}.100"
- description = "testacc_interface_${junos_interface_physical.testacc_interface_logical_phy.name}.100"
- security_zone = junos_security_zone.testacc_interface_logical.name
- routing_instance = junos_routing_instance.testacc_interface_logical.name
+ name = "${junos_interface_physical.testacc_interface_logical_phy.name}.100"
+ description = "testacc_interface_${junos_interface_physical.testacc_interface_logical_phy.name}.100"
+ security_zone = junos_security_zone.testacc_interface_logical.name
+ security_inbound_protocols = ["bgp"]
+ security_inbound_services = ["ssh"]
+ routing_instance = junos_routing_instance.testacc_interface_logical.name
family_inet {
mtu = 1400
filter_input = junos_firewall_filter.testacc_intlogicalInet.name
@@ -318,11 +320,13 @@ resource junos_interface_physical testacc_interface_logical_phy {
vlan_tagging = true
}
resource junos_interface_logical testacc_interface_logical {
- name = "${junos_interface_physical.testacc_interface_logical_phy.name}.100"
- vlan_id = 101
- description = "testacc_interface_${junos_interface_physical.testacc_interface_logical_phy.name}.100"
- security_zone = junos_security_zone.testacc_interface_logical.name
- routing_instance = junos_routing_instance.testacc_interface_logical.name
+ name = "${junos_interface_physical.testacc_interface_logical_phy.name}.100"
+ vlan_id = 101
+ description = "testacc_interface_${junos_interface_physical.testacc_interface_logical_phy.name}.100"
+ security_zone = junos_security_zone.testacc_interface_logical.name
+ security_inbound_protocols = ["ospf"]
+ security_inbound_services = ["telnet"]
+ routing_instance = junos_routing_instance.testacc_interface_logical.name
family_inet {
mtu = 1500
filter_input = junos_firewall_filter.testacc_intlogicalInet.name
diff --git a/junos/resource_interface_physical.go b/junos/resource_interface_physical.go
index 937eff99..dcafa0ce 100644
--- a/junos/resource_interface_physical.go
+++ b/junos/resource_interface_physical.go
@@ -14,15 +14,19 @@ import (
)
type interfacePhysicalOptions struct {
- trunk bool
- vlanTagging bool
- aeMinLink int
- vlanNative int
- aeLacp string
- aeLinkSpeed string
- description string
- v8023ad string
- vlanMembers []string
+ trunk bool
+ vlanTagging bool
+ aeMinLink int
+ vlanNative int
+ aeLacp string
+ aeLinkSpeed string
+ description string
+ v8023ad string
+ vlanMembers []string
+ esi []map[string]interface{}
+ etherOpts []map[string]interface{}
+ gigetherOpts []map[string]interface{}
+ parentEtherOpts []map[string]interface{}
}
func resourceInterfacePhysical() *schema.Resource {
@@ -54,27 +58,144 @@ func resourceInterfacePhysical() *schema.Resource {
Optional: true,
},
"ae_lacp": {
- Type: schema.TypeString,
- Optional: true,
- Default: "",
- ValidateFunc: validation.StringInSlice([]string{"active", "passive"}, false),
+ Type: schema.TypeString,
+ Optional: true,
+ ValidateFunc: validation.StringInSlice([]string{"active", "passive"}, false),
+ ConflictsWith: []string{"parent_ether_opts"},
+ Deprecated: "use parent_ether_opts { lacp } instead",
},
"ae_link_speed": {
- Type: schema.TypeString,
- Optional: true,
- ValidateFunc: validation.StringInSlice([]string{"100m", "1g", "8g", "10g", "40g", "50g", "80g", "100g"}, false),
+ Type: schema.TypeString,
+ Optional: true,
+ ValidateFunc: validation.StringInSlice([]string{"100m", "1g", "8g", "10g", "40g", "50g", "80g", "100g"}, false),
+ ConflictsWith: []string{"parent_ether_opts"},
+ Deprecated: "use parent_ether_opts { link_speed } instead",
},
"ae_minimum_links": {
- Type: schema.TypeInt,
- Optional: true,
+ Type: schema.TypeInt,
+ Optional: true,
+ ConflictsWith: []string{"parent_ether_opts"},
+ Deprecated: "use parent_ether_opts { minimum_links } instead",
},
"description": {
Type: schema.TypeString,
Optional: true,
},
- "ether802_3ad": {
- Type: schema.TypeString,
+ "esi": {
+ Type: schema.TypeList,
Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "mode": {
+ Type: schema.TypeString,
+ Required: true,
+ ValidateFunc: validation.StringInSlice([]string{"all-active", "single-active"}, false),
+ },
+ "auto_derive_lacp": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ConflictsWith: []string{"esi.0.identifier"},
+ },
+ "df_election_type": {
+ Type: schema.TypeString,
+ Optional: true,
+ ValidateFunc: validation.StringInSlice([]string{"mod", "preference"}, false),
+ },
+ "identifier": {
+ Type: schema.TypeString,
+ Optional: true,
+ ConflictsWith: []string{"esi.0.auto_derive_lacp"},
+ ValidateFunc: validation.StringMatch(regexp.MustCompile(
+ `^([\d\w]{2}:){9}[\d\w]{2}$`), "bad format or length"),
+ },
+ "source_bmac": {
+ Type: schema.TypeString,
+ Optional: true,
+ ValidateFunc: validation.IsMACAddress,
+ },
+ },
+ },
+ },
+ "ether_opts": {
+ Type: schema.TypeList,
+ Optional: true,
+ ConflictsWith: []string{
+ "ae_lacp", "ae_link_speed", "ae_minimum_links",
+ "gigether_opts", "parent_ether_opts",
+ },
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "ae_8023ad": {
+ Type: schema.TypeString,
+ Optional: true,
+ ConflictsWith: []string{"ether_opts.0.redundant_parent"},
+ ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
+ value := v.(string)
+ if !strings.HasPrefix(value, "ae") {
+ errors = append(errors, fmt.Errorf(
+ "%q in %q isn't an ae interface", value, k))
+ }
+
+ return
+ },
+ },
+ "auto_negotiation": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ConflictsWith: []string{"gigether_opts.0.no_auto_negotiation"},
+ },
+ "no_auto_negotiation": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ConflictsWith: []string{"gigether_opts.0.auto_negotiation"},
+ },
+ "flow_control": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ConflictsWith: []string{"gigether_opts.0.no_flow_control"},
+ },
+ "no_flow_control": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ConflictsWith: []string{"gigether_opts.0.flow_control"},
+ },
+ "loopback": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ConflictsWith: []string{"gigether_opts.0.no_loopback"},
+ },
+ "no_loopback": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ConflictsWith: []string{"gigether_opts.0.loopback"},
+ },
+ "redundant_parent": {
+ Type: schema.TypeString,
+ Optional: true,
+ ConflictsWith: []string{"ether_opts.0.ae_8023ad"},
+ ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
+ value := v.(string)
+ if !strings.HasPrefix(value, "reth") {
+ errors = append(errors, fmt.Errorf(
+ "%q in %q isn't an reth interface", value, k))
+ }
+
+ return
+ },
+ },
+ },
+ },
+ },
+ "ether802_3ad": {
+ Type: schema.TypeString,
+ Optional: true,
+ Deprecated: "use ether_opts { ae_8023ad } or gigether_opts { ae_8023ad } instead",
+ ConflictsWith: []string{
+ "ae_lacp", "ae_link_speed", "ae_minimum_links",
+ "ether_opts", "gigether_opts",
+ },
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if !strings.HasPrefix(value, "ae") {
@@ -85,6 +206,265 @@ func resourceInterfacePhysical() *schema.Resource {
return
},
},
+ "gigether_opts": {
+ Type: schema.TypeList,
+ Optional: true,
+ ConflictsWith: []string{
+ "ae_lacp", "ae_link_speed", "ae_minimum_links",
+ "ether_opts", "ether802_3ad", "parent_ether_opts",
+ },
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "ae_8023ad": {
+ Type: schema.TypeString,
+ Optional: true,
+ ConflictsWith: []string{"gigether_opts.0.redundant_parent"},
+ ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
+ value := v.(string)
+ if !strings.HasPrefix(value, "ae") {
+ errors = append(errors, fmt.Errorf(
+ "%q in %q isn't an ae interface", value, k))
+ }
+
+ return
+ },
+ },
+ "auto_negotiation": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ConflictsWith: []string{"gigether_opts.0.no_auto_negotiation"},
+ },
+ "no_auto_negotiation": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ConflictsWith: []string{"gigether_opts.0.auto_negotiation"},
+ },
+ "flow_control": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ConflictsWith: []string{"gigether_opts.0.no_flow_control"},
+ },
+ "no_flow_control": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ConflictsWith: []string{"gigether_opts.0.flow_control"},
+ },
+ "loopback": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ConflictsWith: []string{"gigether_opts.0.no_loopback"},
+ },
+ "no_loopback": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ConflictsWith: []string{"gigether_opts.0.loopback"},
+ },
+ "redundant_parent": {
+ Type: schema.TypeString,
+ Optional: true,
+ ConflictsWith: []string{"gigether_opts.0.ae_8023ad"},
+ ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
+ value := v.(string)
+ if !strings.HasPrefix(value, "reth") {
+ errors = append(errors, fmt.Errorf(
+ "%q in %q isn't an reth interface", value, k))
+ }
+
+ return
+ },
+ },
+ },
+ },
+ },
+ "parent_ether_opts": {
+ Type: schema.TypeList,
+ Optional: true,
+ ConflictsWith: []string{
+ "ae_lacp", "ae_link_speed", "ae_minimum_links",
+ "ether_opts", "ether802_3ad", "gigether_opts",
+ },
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "bfd_liveness_detection": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "local_address": {
+ Type: schema.TypeString,
+ Required: true,
+ ValidateFunc: validation.IsIPAddress,
+ },
+ "authentication_algorithm": {
+ Type: schema.TypeString,
+ Optional: true,
+ ValidateFunc: validation.StringInSlice([]string{
+ "keyed-md5", "keyed-sha-1", "meticulous-keyed-md5", "meticulous-keyed-sha-1", "simple-password",
+ }, false),
+ },
+ "authentication_key_chain": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "authentication_loose_check": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ "detection_time_threshold": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(1, 4294967295),
+ },
+ "holddown_interval": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(1, 255000),
+ },
+ "minimum_interval": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(1, 255000),
+ },
+ "minimum_receive_interval": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(1, 255000),
+ },
+ "multiplier": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(1, 255),
+ },
+ "neighbor": {
+ Type: schema.TypeString,
+ Optional: true,
+ ValidateFunc: validation.IsIPAddress,
+ },
+ "no_adaptation": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ "transmit_interval_minimum_interval": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(1, 255000),
+ },
+ "transmit_interval_threshold": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(1, 4294967295),
+ },
+ "version": {
+ Type: schema.TypeString,
+ Optional: true,
+ ValidateFunc: validation.StringInSlice([]string{"0", "1", "automatic"}, false),
+ },
+ },
+ },
+ },
+ "flow_control": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ConflictsWith: []string{"parent_ether_opts.0.no_flow_control"},
+ },
+ "no_flow_control": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ConflictsWith: []string{"parent_ether_opts.0.flow_control"},
+ },
+ "lacp": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "mode": {
+ Type: schema.TypeString,
+ Required: true,
+ ValidateFunc: validation.StringInSlice([]string{"active", "passive"}, false),
+ },
+ "admin_key": {
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: -1,
+ ValidateFunc: validation.IntBetween(0, 65535),
+ },
+ "periodic": {
+ Type: schema.TypeString,
+ Optional: true,
+ ValidateFunc: validation.StringInSlice([]string{"fast", "slow"}, false),
+ },
+ "sync_reset": {
+ Type: schema.TypeString,
+ Optional: true,
+ ValidateFunc: validation.StringInSlice([]string{"disable", "enable"}, false),
+ },
+ "system_id": {
+ Type: schema.TypeString,
+ Optional: true,
+ ValidateFunc: validation.IsMACAddress,
+ },
+ "system_priority": {
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: -1,
+ ValidateFunc: validation.IntBetween(0, 65535),
+ },
+ },
+ },
+ },
+ "loopback": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ConflictsWith: []string{"parent_ether_opts.0.no_loopback"},
+ },
+ "no_loopback": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ConflictsWith: []string{"parent_ether_opts.0.loopback"},
+ },
+ "link_speed": {
+ Type: schema.TypeString,
+ Optional: true,
+ ValidateFunc: validation.StringInSlice([]string{
+ "100m",
+ "1g", "2.5g", "5g", "8g",
+ "10g", "25g", "40g", "50g", "80g",
+ "100g", "400g", "mixed"}, false),
+ },
+ "minimum_bandwidth": {
+ Type: schema.TypeString,
+ Optional: true,
+ ConflictsWith: []string{"parent_ether_opts.0.minimum_links"},
+ ValidateFunc: validation.StringMatch(regexp.MustCompile(
+ `^[0-9]+ (k|g|m)?bps$`), "must be 'N (k|g|m)?bps' format"),
+ },
+ "minimum_links": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ConflictsWith: []string{"parent_ether_opts.0.minimum_bandwidth"},
+ ValidateFunc: validation.IntBetween(1, 64),
+ },
+ "redundancy_group": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(1, 128),
+ },
+ "source_address_filter": {
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ "source_filtering": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ },
+ },
+ },
"trunk": {
Type: schema.TypeBool,
Optional: true,
@@ -109,6 +489,17 @@ func resourceInterfacePhysical() *schema.Resource {
func resourceInterfacePhysicalCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := delInterfaceNC(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ if err := setInterfacePhysical(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -230,6 +621,11 @@ func resourceInterfacePhysicalUpdate(ctx context.Context, d *schema.ResourceData
return diag.FromErr(err)
}
+ if err := unsetInterfacePhysicalAE(d, m, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
if err := setInterfacePhysical(d, m, jnprSess); err != nil {
sess.configClear(jnprSess)
@@ -406,6 +802,47 @@ func checkInterfaceExists(interFace string, m interface{}, jnprSess *NetconfObje
return true, nil
}
+func unsetInterfacePhysicalAE(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
+ sess := m.(*Session)
+ var oldAE string
+ switch {
+ case d.HasChange("ether802_3ad"):
+ oldAEtf, _ := d.GetChange("ether802_3ad")
+ if oldAEtf.(string) != "" {
+ oldAE = oldAEtf.(string)
+ }
+ case d.HasChange("ether_opts"):
+ oldEthOpts, _ := d.GetChange("ether_opts")
+ if len(oldEthOpts.([]interface{})) != 0 {
+ v := oldEthOpts.([]interface{})[0]
+ if o := v.(map[string]interface{})["ae_8023ad"].(string); o != "" {
+ oldAE = o
+ }
+ }
+ case d.HasChange("gigether_opts"):
+ oldGigethOpts, _ := d.GetChange("gigether_opts")
+ if len(oldGigethOpts.([]interface{})) != 0 {
+ v := oldGigethOpts.([]interface{})[0]
+ if o := v.(map[string]interface{})["ae_8023ad"].(string); o != "" {
+ oldAE = o
+ }
+ }
+ }
+ if oldAE != "" {
+ aggregatedCount, err := interfaceAggregatedCountSearchMax("ae-1", oldAE, d.Get("name").(string), m, jnprSess)
+ if err != nil {
+ return err
+ }
+ if aggregatedCount == "0" {
+ return sess.configSet([]string{"delete chassis aggregated-devices ethernet device-count"}, jnprSess)
+ }
+
+ return sess.configSet([]string{"set chassis aggregated-devices ethernet device-count " + aggregatedCount}, jnprSess)
+ }
+
+ return nil
+}
+
func setInterfacePhysical(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
configSet := make([]string, 0)
@@ -435,30 +872,136 @@ func setInterfacePhysical(d *schema.ResourceData, m interface{}, jnprSess *Netco
if d.Get("description").(string) != "" {
configSet = append(configSet, setPrefix+"description \""+d.Get("description").(string)+"\"")
}
- if v := d.Get("name").(string); strings.HasPrefix(v, "ae") {
+ if err := setInterfacePhysicalEsi(setPrefix, d.Get("esi").([]interface{}), m, jnprSess); err != nil {
+ return err
+ }
+ if v := d.Get("name").(string); strings.HasPrefix(v, "ae") && jnprSess != nil {
aggregatedCount, err := interfaceAggregatedCountSearchMax(v, "ae-1", v, m, jnprSess)
if err != nil {
return err
}
configSet = append(configSet, "set chassis aggregated-devices ethernet device-count "+aggregatedCount)
- } else if d.Get("ether802_3ad").(string) != "" {
- configSet = append(configSet, setPrefix+"ether-options 802.3ad "+
- d.Get("ether802_3ad").(string))
- configSet = append(configSet, setPrefix+"gigether-options 802.3ad "+
- d.Get("ether802_3ad").(string))
+ } else if d.Get("ether802_3ad").(string) != "" ||
+ len(d.Get("ether_opts").([]interface{})) != 0 ||
+ len(d.Get("gigether_opts").([]interface{})) != 0 {
oldAE := "ae-1"
- if d.HasChange("ether802_3ad") {
+ var newAE string
+ switch {
+ case d.Get("ether802_3ad").(string) != "":
+ newAE = d.Get("ether802_3ad").(string)
+ configSet = append(configSet, setPrefix+"ether-options 802.3ad "+
+ d.Get("ether802_3ad").(string))
+ configSet = append(configSet, setPrefix+"gigether-options 802.3ad "+
+ d.Get("ether802_3ad").(string))
+ case len(d.Get("ether_opts").([]interface{})) != 0:
+ for _, v := range d.Get("ether_opts").([]interface{}) {
+ if v == nil {
+ return fmt.Errorf("ether_opts block is empty")
+ }
+ m := v.(map[string]interface{})
+ if m["ae_8023ad"].(string) != "" {
+ newAE = m["ae_8023ad"].(string)
+ configSet = append(configSet, setPrefix+"ether-options 802.3ad "+
+ m["ae_8023ad"].(string))
+ }
+ if m["auto_negotiation"].(bool) {
+ configSet = append(configSet, setPrefix+"ether-options auto-negotiation")
+ }
+ if m["no_auto_negotiation"].(bool) {
+ configSet = append(configSet, setPrefix+"ether-options no-auto-negotiation")
+ }
+ if m["flow_control"].(bool) {
+ configSet = append(configSet, setPrefix+"ether-options flow-control")
+ }
+ if m["no_flow_control"].(bool) {
+ configSet = append(configSet, setPrefix+"ether-options no-flow-control")
+ }
+ if m["loopback"].(bool) {
+ configSet = append(configSet, setPrefix+"ether-options loopback")
+ }
+ if m["no_loopback"].(bool) {
+ configSet = append(configSet, setPrefix+"ether-options no-loopback")
+ }
+ if m["redundant_parent"].(string) != "" {
+ configSet = append(configSet, setPrefix+"ether-options redundant-parent "+
+ m["redundant_parent"].(string))
+ }
+ }
+ case len(d.Get("gigether_opts").([]interface{})) != 0:
+ for _, v := range d.Get("gigether_opts").([]interface{}) {
+ if v == nil {
+ return fmt.Errorf("gigether_opts block is empty")
+ }
+ m := v.(map[string]interface{})
+ if m["ae_8023ad"].(string) != "" {
+ newAE = m["ae_8023ad"].(string)
+ configSet = append(configSet, setPrefix+"gigether-options 802.3ad "+
+ m["ae_8023ad"].(string))
+ }
+ if m["auto_negotiation"].(bool) {
+ configSet = append(configSet, setPrefix+"gigether-options auto-negotiation")
+ }
+ if m["no_auto_negotiation"].(bool) {
+ configSet = append(configSet, setPrefix+"gigether-options no-auto-negotiation")
+ }
+ if m["flow_control"].(bool) {
+ configSet = append(configSet, setPrefix+"gigether-options flow-control")
+ }
+ if m["no_flow_control"].(bool) {
+ configSet = append(configSet, setPrefix+"gigether-options no-flow-control")
+ }
+ if m["loopback"].(bool) {
+ configSet = append(configSet, setPrefix+"gigether-options loopback")
+ }
+ if m["no_loopback"].(bool) {
+ configSet = append(configSet, setPrefix+"gigether-options no-loopback")
+ }
+ if m["redundant_parent"].(string) != "" {
+ configSet = append(configSet, setPrefix+"gigether-options redundant-parent "+
+ m["redundant_parent"].(string))
+ }
+ }
+ }
+ switch {
+ case d.HasChange("ether802_3ad"):
oldAEtf, _ := d.GetChange("ether802_3ad")
if oldAEtf.(string) != "" {
oldAE = oldAEtf.(string)
}
+ case d.HasChange("ether_opts"):
+ oldEthOpts, _ := d.GetChange("ether_opts")
+ if len(oldEthOpts.([]interface{})) != 0 {
+ v := oldEthOpts.([]interface{})[0]
+ if o := v.(map[string]interface{})["ae_8023ad"].(string); o != "" {
+ oldAE = o
+ }
+ }
+ case d.HasChange("gigether_opts"):
+ oldGigethOpts, _ := d.GetChange("gigether_opts")
+ if len(oldGigethOpts.([]interface{})) != 0 {
+ v := oldGigethOpts.([]interface{})[0]
+ if o := v.(map[string]interface{})["ae_8023ad"].(string); o != "" {
+ oldAE = o
+ }
+ }
}
- aggregatedCount, err := interfaceAggregatedCountSearchMax(d.Get("ether802_3ad").(string), oldAE,
- d.Get("name").(string), m, jnprSess)
- if err != nil {
+ if newAE != "" && jnprSess != nil {
+ aggregatedCount, err := interfaceAggregatedCountSearchMax(newAE, oldAE,
+ d.Get("name").(string), m, jnprSess)
+ if err != nil {
+ return err
+ }
+ configSet = append(configSet, "set chassis aggregated-devices ethernet device-count "+aggregatedCount)
+ }
+ }
+ for _, v := range d.Get("parent_ether_opts").([]interface{}) {
+ if v == nil {
+ return fmt.Errorf("parent_ether_opts block is empty")
+ }
+ if err := setInterfacePhysicalParentEtherOpts(
+ v.(map[string]interface{}), d.Get("name").(string), m, jnprSess); err != nil {
return err
}
- configSet = append(configSet, "set chassis aggregated-devices ethernet device-count "+aggregatedCount)
}
if d.Get("trunk").(bool) {
configSet = append(configSet, setPrefix+"unit 0 family ethernet-switching interface-mode trunk")
@@ -474,12 +1017,152 @@ func setInterfacePhysical(d *schema.ResourceData, m interface{}, jnprSess *Netco
configSet = append(configSet, setPrefix+"vlan-tagging")
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
+ return sess.configSet(configSet, jnprSess)
+}
+
+func setInterfacePhysicalEsi(setPrefix string, esiParams []interface{},
+ m interface{}, jnprSess *NetconfObject) error {
+ sess := m.(*Session)
+ configSet := make([]string, 0)
+
+ for _, v := range esiParams {
+ m := v.(map[string]interface{})
+ if m["mode"].(string) != "" {
+ configSet = append(configSet, setPrefix+"esi "+m["mode"].(string))
+ }
+ if m["auto_derive_lacp"].(bool) {
+ configSet = append(configSet, setPrefix+"esi auto-derive lacp")
+ }
+ if m["df_election_type"].(string) != "" {
+ configSet = append(configSet, setPrefix+"esi df-election-type "+m["df_election_type"].(string))
+ }
+ if m["identifier"].(string) != "" {
+ configSet = append(configSet, setPrefix+"esi "+m["identifier"].(string))
+ }
+ if m["source_bmac"].(string) != "" {
+ configSet = append(configSet, setPrefix+"esi source-bmac "+m["source_bmac"].(string))
+ }
}
- return nil
+ return sess.configSet(configSet, jnprSess)
+}
+func setInterfacePhysicalParentEtherOpts(
+ ethOpts map[string]interface{}, interfaceName string, m interface{}, jnprSess *NetconfObject) error {
+ sess := m.(*Session)
+ configSet := make([]string, 0)
+ setPrefix := "set interfaces " + interfaceName + " "
+ switch {
+ case strings.HasPrefix(interfaceName, "ae"):
+ setPrefix += "aggregated-ether-options "
+ case strings.HasPrefix(interfaceName, "reth"):
+ setPrefix += "redundant-ether-options "
+ default:
+ return fmt.Errorf("parent_ether_opts not compatible with this interface %s "+
+ "(need to ae* or reth*)", interfaceName)
+ }
+
+ for _, v := range ethOpts["bfd_liveness_detection"].([]interface{}) {
+ bfdLiveDetect := v.(map[string]interface{})
+ configSet = append(configSet, setPrefix+
+ "bfd-liveness-detection local-address "+bfdLiveDetect["local_address"].(string))
+ if v2 := bfdLiveDetect["authentication_algorithm"].(string); v2 != "" {
+ configSet = append(configSet, setPrefix+"bfd-liveness-detection authentication algorithm "+v2)
+ }
+ if v2 := bfdLiveDetect["authentication_key_chain"].(string); v2 != "" {
+ configSet = append(configSet, setPrefix+"bfd-liveness-detection authentication key-chain "+v2)
+ }
+ if bfdLiveDetect["authentication_loose_check"].(bool) {
+ configSet = append(configSet, setPrefix+"bfd-liveness-detection authentication loose-check")
+ }
+ if v2 := bfdLiveDetect["detection_time_threshold"].(int); v2 != 0 {
+ configSet = append(configSet, setPrefix+"bfd-liveness-detection detection-time threshold "+strconv.Itoa(v2))
+ }
+ if v2 := bfdLiveDetect["holddown_interval"].(int); v2 != 0 {
+ configSet = append(configSet, setPrefix+"bfd-liveness-detection holddown-interval "+strconv.Itoa(v2))
+ }
+ if v2 := bfdLiveDetect["minimum_interval"].(int); v2 != 0 {
+ configSet = append(configSet, setPrefix+"bfd-liveness-detection minimum-interval "+strconv.Itoa(v2))
+ }
+ if v2 := bfdLiveDetect["minimum_receive_interval"].(int); v2 != 0 {
+ configSet = append(configSet, setPrefix+"bfd-liveness-detection minimum-receive-interval "+strconv.Itoa(v2))
+ }
+ if v2 := bfdLiveDetect["multiplier"].(int); v2 != 0 {
+ configSet = append(configSet, setPrefix+"bfd-liveness-detection multiplier "+strconv.Itoa(v2))
+ }
+ if v2 := bfdLiveDetect["neighbor"].(string); v2 != "" {
+ configSet = append(configSet, setPrefix+"bfd-liveness-detection neighbor "+v2)
+ }
+ if bfdLiveDetect["no_adaptation"].(bool) {
+ configSet = append(configSet, setPrefix+"bfd-liveness-detection no-adaptation")
+ }
+ if v2 := bfdLiveDetect["transmit_interval_minimum_interval"].(int); v2 != 0 {
+ configSet = append(configSet, setPrefix+
+ "bfd-liveness-detection transmit-interval minimum-interval "+strconv.Itoa(v2))
+ }
+ if v2 := bfdLiveDetect["transmit_interval_threshold"].(int); v2 != 0 {
+ configSet = append(configSet, setPrefix+"bfd-liveness-detection transmit-interval threshold "+strconv.Itoa(v2))
+ }
+ if v2 := bfdLiveDetect["version"].(string); v2 != "" {
+ configSet = append(configSet, setPrefix+"bfd-liveness-detection version "+v2)
+ }
+ }
+ if ethOpts["flow_control"].(bool) {
+ configSet = append(configSet, setPrefix+flowControlWords)
+ }
+ if ethOpts["no_flow_control"].(bool) {
+ configSet = append(configSet, setPrefix+noFlowControlWords)
+ }
+ for _, v := range ethOpts["lacp"].([]interface{}) {
+ lacp := v.(map[string]interface{})
+ configSet = append(configSet, setPrefix+"lacp "+lacp["mode"].(string))
+ if v2 := lacp["admin_key"].(int); v2 != -1 {
+ configSet = append(configSet, setPrefix+"lacp admin-key "+strconv.Itoa(v2))
+ }
+ if v2 := lacp["periodic"].(string); v2 != "" {
+ configSet = append(configSet, setPrefix+"lacp periodic "+v2)
+ }
+ if v2 := lacp["sync_reset"].(string); v2 != "" {
+ configSet = append(configSet, setPrefix+"lacp sync-reset "+v2)
+ }
+ if v2 := lacp["system_id"].(string); v2 != "" {
+ configSet = append(configSet, setPrefix+"lacp system-id "+v2)
+ }
+ if v2 := lacp["system_priority"].(int); v2 != -1 {
+ configSet = append(configSet, setPrefix+"lacp system-priority "+strconv.Itoa(v2))
+ }
+ }
+ if ethOpts["loopback"].(bool) {
+ configSet = append(configSet, setPrefix+loopbackWord)
+ }
+ if ethOpts["no_loopback"].(bool) {
+ configSet = append(configSet, setPrefix+noLoopbackWord)
+ }
+ if v := ethOpts["link_speed"].(string); v != "" {
+ configSet = append(configSet, setPrefix+"link-speed "+v)
+ }
+ if v := ethOpts["minimum_bandwidth"].(string); v != "" {
+ vS := strings.Split(v, " ")
+ configSet = append(configSet, setPrefix+"minimum-bandwidth bw-value "+vS[0])
+ if len(vS) > 1 {
+ configSet = append(configSet, setPrefix+"minimum-bandwidth bw-unit "+vS[1])
+ }
+ }
+ if v := ethOpts["minimum_links"].(int); v != 0 {
+ configSet = append(configSet, setPrefix+"minimum-links "+strconv.Itoa(v))
+ }
+ if v := ethOpts["redundancy_group"].(int); v != 0 {
+ configSet = append(configSet, setPrefix+"redundancy-group "+strconv.Itoa(v))
+ }
+ for _, v := range ethOpts["source_address_filter"].([]interface{}) {
+ configSet = append(configSet, setPrefix+"source-address-filter "+v.(string))
+ }
+ if ethOpts["source_filtering"].(bool) {
+ configSet = append(configSet, setPrefix+"source-filtering")
+ }
+
+ return sess.configSet(configSet, jnprSess)
}
+
func readInterfacePhysical(interFace string, m interface{}, jnprSess *NetconfObject) (interfacePhysicalOptions, error) {
sess := m.(*Session)
var confRead interfacePhysicalOptions
@@ -503,21 +1186,46 @@ func readInterfacePhysical(interFace string, m interface{}, jnprSess *NetconfObj
switch {
case strings.HasPrefix(itemTrim, "aggregated-ether-options lacp "):
confRead.aeLacp = strings.TrimPrefix(itemTrim, "aggregated-ether-options lacp ")
+ if err := readInterfacePhysicalParentEtherOpts(&confRead,
+ strings.TrimPrefix(itemTrim, "aggregated-ether-options ")); err != nil {
+ return confRead, err
+ }
case strings.HasPrefix(itemTrim, "aggregated-ether-options link-speed "):
confRead.aeLinkSpeed = strings.TrimPrefix(itemTrim, "aggregated-ether-options link-speed ")
+ if err := readInterfacePhysicalParentEtherOpts(&confRead,
+ strings.TrimPrefix(itemTrim, "aggregated-ether-options ")); err != nil {
+ return confRead, err
+ }
case strings.HasPrefix(itemTrim, "aggregated-ether-options minimum-links "):
confRead.aeMinLink, err = strconv.Atoi(strings.TrimPrefix(itemTrim,
"aggregated-ether-options minimum-links "))
if err != nil {
return confRead, fmt.Errorf("failed to convert value from '%s' to integer : %w", itemTrim, err)
}
+ if err := readInterfacePhysicalParentEtherOpts(&confRead,
+ strings.TrimPrefix(itemTrim, "aggregated-ether-options ")); err != nil {
+ return confRead, err
+ }
+ case strings.HasPrefix(itemTrim, "aggregated-ether-options "):
+ if err := readInterfacePhysicalParentEtherOpts(&confRead,
+ strings.TrimPrefix(itemTrim, "aggregated-ether-options ")); err != nil {
+ return confRead, err
+ }
+ case strings.HasPrefix(itemTrim, "redundant-ether-options "):
+ if err := readInterfacePhysicalParentEtherOpts(&confRead,
+ strings.TrimPrefix(itemTrim, "redundant-ether-options ")); err != nil {
+ return confRead, err
+ }
case strings.HasPrefix(itemTrim, "description "):
confRead.description = strings.Trim(strings.TrimPrefix(itemTrim, "description "), "\"")
-
- case strings.HasPrefix(itemTrim, "ether-options 802.3ad "):
- confRead.v8023ad = strings.TrimPrefix(itemTrim, "ether-options 802.3ad ")
- case strings.HasPrefix(itemTrim, "gigether-options 802.3ad "):
- confRead.v8023ad = strings.TrimPrefix(itemTrim, "gigether-options 802.3ad ")
+ case strings.HasPrefix(itemTrim, "esi "):
+ if err := readInterfacePhysicalEsi(&confRead, itemTrim); err != nil {
+ return confRead, err
+ }
+ case strings.HasPrefix(itemTrim, "ether-options "):
+ readInterfacePhysicalEtherOpts(&confRead, strings.TrimPrefix(itemTrim, "ether-options "))
+ case strings.HasPrefix(itemTrim, "gigether-options "):
+ readInterfacePhysicalGigetherOpts(&confRead, strings.TrimPrefix(itemTrim, "gigether-options "))
case strings.HasPrefix(itemTrim, "native-vlan-id"):
confRead.vlanNative, err = strconv.Atoi(strings.TrimPrefix(itemTrim, "native-vlan-id "))
if err != nil {
@@ -538,6 +1246,296 @@ func readInterfacePhysical(interFace string, m interface{}, jnprSess *NetconfObj
return confRead, nil
}
+func readInterfacePhysicalEsi(confRead *interfacePhysicalOptions, item string) error {
+ itemTrim := strings.TrimPrefix(item, "esi ")
+ if len(confRead.esi) == 0 {
+ confRead.esi = append(confRead.esi, map[string]interface{}{
+ "mode": "",
+ "auto_derive_lacp": false,
+ "df_election_type": "",
+ "identifier": "",
+ "source_bmac": "",
+ })
+ }
+ var err error
+ identifier, err := regexp.MatchString(`^([\d\w]{2}:){9}[\d\w]{2}`, itemTrim)
+ if err != nil {
+ return fmt.Errorf("esi_identifier regexp error : %w", err)
+ }
+ switch {
+ case identifier:
+ confRead.esi[0]["identifier"] = itemTrim
+ case itemTrim == "all-active" || itemTrim == "single-active":
+ confRead.esi[0]["mode"] = itemTrim
+ case strings.HasPrefix(itemTrim, "df-election-type "):
+ confRead.esi[0]["df_election_type"] = strings.TrimPrefix(itemTrim, "df-election-type ")
+ case strings.HasPrefix(itemTrim, "source-bmac "):
+ confRead.esi[0]["source_bmac"] = strings.TrimPrefix(itemTrim, "source-bmac ")
+ case itemTrim == "auto-derive lacp":
+ confRead.esi[0]["auto_derive_lacp"] = true
+ }
+
+ return nil
+}
+func readInterfacePhysicalEtherOpts(confRead *interfacePhysicalOptions, itemTrim string) {
+ if len(confRead.etherOpts) == 0 {
+ confRead.etherOpts = append(confRead.etherOpts, map[string]interface{}{
+ "ae_8023ad": "",
+ "auto_negotiation": false,
+ "no_auto_negotiation": false,
+ "flow_control": false,
+ "no_flow_control": false,
+ "loopback": false,
+ "no_loopback": false,
+ "redundant_parent": "",
+ })
+ }
+ switch {
+ case strings.HasPrefix(itemTrim, "802.3ad "):
+ confRead.v8023ad = strings.TrimPrefix(itemTrim, "802.3ad ")
+ confRead.etherOpts[0]["ae_8023ad"] = strings.TrimPrefix(itemTrim, "802.3ad ")
+ case itemTrim == "auto-negotiation":
+ confRead.etherOpts[0]["auto_negotiation"] = true
+ case itemTrim == "no-auto-negotiation":
+ confRead.etherOpts[0]["no_auto_negotiation"] = true
+ case itemTrim == flowControlWords:
+ confRead.etherOpts[0]["flow_control"] = true
+ case itemTrim == noFlowControlWords:
+ confRead.etherOpts[0]["no_flow_control"] = true
+ case itemTrim == loopbackWord:
+ confRead.etherOpts[0]["loopback"] = true
+ case itemTrim == noLoopbackWord:
+ confRead.etherOpts[0]["no_loopback"] = true
+ case strings.HasPrefix(itemTrim, "redundant-parent "):
+ confRead.etherOpts[0]["redundant_parent"] = strings.TrimPrefix(itemTrim, "redundant-parent ")
+ }
+}
+func readInterfacePhysicalGigetherOpts(confRead *interfacePhysicalOptions, itemTrim string) {
+ if len(confRead.gigetherOpts) == 0 {
+ confRead.gigetherOpts = append(confRead.gigetherOpts, map[string]interface{}{
+ "ae_8023ad": "",
+ "auto_negotiation": false,
+ "no_auto_negotiation": false,
+ "flow_control": false,
+ "no_flow_control": false,
+ "loopback": false,
+ "no_loopback": false,
+ "redundant_parent": "",
+ })
+ }
+ switch {
+ case strings.HasPrefix(itemTrim, "802.3ad "):
+ confRead.v8023ad = strings.TrimPrefix(itemTrim, "802.3ad ")
+ confRead.gigetherOpts[0]["ae_8023ad"] = strings.TrimPrefix(itemTrim, "802.3ad ")
+ case itemTrim == "auto-negotiation":
+ confRead.gigetherOpts[0]["auto_negotiation"] = true
+ case itemTrim == "no-auto-negotiation":
+ confRead.gigetherOpts[0]["no_auto_negotiation"] = true
+ case itemTrim == flowControlWords:
+ confRead.gigetherOpts[0]["flow_control"] = true
+ case itemTrim == noFlowControlWords:
+ confRead.gigetherOpts[0]["no_flow_control"] = true
+ case itemTrim == loopbackWord:
+ confRead.gigetherOpts[0]["loopback"] = true
+ case itemTrim == noLoopbackWord:
+ confRead.gigetherOpts[0]["no_loopback"] = true
+ case strings.HasPrefix(itemTrim, "redundant-parent "):
+ confRead.gigetherOpts[0]["redundant_parent"] = strings.TrimPrefix(itemTrim, "redundant-parent ")
+ }
+}
+func readInterfacePhysicalParentEtherOpts(confRead *interfacePhysicalOptions, itemTrim string) error {
+ if len(confRead.parentEtherOpts) == 0 {
+ confRead.parentEtherOpts = append(confRead.parentEtherOpts, map[string]interface{}{
+ "bfd_liveness_detection": make([]map[string]interface{}, 0),
+ "flow_control": false,
+ "no_flow_control": false,
+ "lacp": make([]map[string]interface{}, 0),
+ "loopback": false,
+ "no_loopback": false,
+ "link_speed": "",
+ "minimum_bandwidth": "",
+ "minimum_links": 0,
+ "redundancy_group": 0,
+ "source_address_filter": make([]string, 0),
+ "source_filtering": false,
+ })
+ }
+ switch {
+ case strings.HasPrefix(itemTrim, "bfd-liveness-detection "):
+ if len(confRead.parentEtherOpts[0]["bfd_liveness_detection"].([]map[string]interface{})) == 0 {
+ confRead.parentEtherOpts[0]["bfd_liveness_detection"] = append(
+ confRead.parentEtherOpts[0]["bfd_liveness_detection"].([]map[string]interface{}),
+ map[string]interface{}{
+ "local_address": "",
+ "authentication_algorithm": "",
+ "authentication_key_chain": "",
+ "authentication_loose_check": false,
+ "detection_time_threshold": 0,
+ "holddown_interval": 0,
+ "minimum_interval": 0,
+ "minimum_receive_interval": 0,
+ "multiplier": 0,
+ "neighbor": "",
+ "no_adaptation": false,
+ "transmit_interval_minimum_interval": 0,
+ "transmit_interval_threshold": 0,
+ "version": "",
+ })
+ }
+ itemTrimBfdLiveDet := strings.TrimPrefix(itemTrim, "bfd-liveness-detection ")
+ switch {
+ case strings.HasPrefix(itemTrimBfdLiveDet, "local-address "):
+ confRead.parentEtherOpts[0]["bfd_liveness_detection"].([]map[string]interface{})[0]["local_address"] =
+ strings.TrimPrefix(itemTrimBfdLiveDet, "local-address ")
+ case strings.HasPrefix(itemTrimBfdLiveDet, "authentication algorithm "):
+ confRead.parentEtherOpts[0]["bfd_liveness_detection"].([]map[string]interface{})[0]["authentication_algorithm"] =
+ strings.TrimPrefix(itemTrimBfdLiveDet, "authentication algorithm ")
+ case strings.HasPrefix(itemTrimBfdLiveDet, "authentication key-chain "):
+ confRead.parentEtherOpts[0]["bfd_liveness_detection"].([]map[string]interface{})[0]["authentication_key_chain"] =
+ strings.TrimPrefix(itemTrimBfdLiveDet, "authentication key-chain ")
+ case itemTrimBfdLiveDet == "authentication loose-check":
+ confRead.parentEtherOpts[0]["bfd_liveness_detection"].([]map[string]interface{})[0]["authentication_loose_check"] =
+ true
+ case strings.HasPrefix(itemTrimBfdLiveDet, "detection-time threshold "):
+ var err error
+ confRead.parentEtherOpts[0]["bfd_liveness_detection"].([]map[string]interface{})[0]["detection_time_threshold"],
+ err = strconv.Atoi(strings.TrimPrefix(itemTrimBfdLiveDet, "detection-time threshold "))
+ if err != nil {
+ return fmt.Errorf("failed to convert value from '%s' to integer : %w", itemTrim, err)
+ }
+ case strings.HasPrefix(itemTrimBfdLiveDet, "holddown-interval "):
+ var err error
+ confRead.parentEtherOpts[0]["bfd_liveness_detection"].([]map[string]interface{})[0]["holddown_interval"],
+ err = strconv.Atoi(strings.TrimPrefix(itemTrimBfdLiveDet, "holddown-interval "))
+ if err != nil {
+ return fmt.Errorf("failed to convert value from '%s' to integer : %w", itemTrim, err)
+ }
+ case strings.HasPrefix(itemTrimBfdLiveDet, "minimum-interval "):
+ var err error
+ confRead.parentEtherOpts[0]["bfd_liveness_detection"].([]map[string]interface{})[0]["minimum_interval"],
+ err = strconv.Atoi(strings.TrimPrefix(itemTrimBfdLiveDet, "minimum-interval "))
+ if err != nil {
+ return fmt.Errorf("failed to convert value from '%s' to integer : %w", itemTrim, err)
+ }
+ case strings.HasPrefix(itemTrimBfdLiveDet, "minimum-receive-interval "):
+ var err error
+ confRead.parentEtherOpts[0]["bfd_liveness_detection"].([]map[string]interface{})[0]["minimum_receive_interval"],
+ err = strconv.Atoi(strings.TrimPrefix(itemTrimBfdLiveDet, "minimum-receive-interval "))
+ if err != nil {
+ return fmt.Errorf("failed to convert value from '%s' to integer : %w", itemTrim, err)
+ }
+ case strings.HasPrefix(itemTrimBfdLiveDet, "multiplier "):
+ var err error
+ confRead.parentEtherOpts[0]["bfd_liveness_detection"].([]map[string]interface{})[0]["multiplier"],
+ err = strconv.Atoi(strings.TrimPrefix(itemTrimBfdLiveDet, "multiplier "))
+ if err != nil {
+ return fmt.Errorf("failed to convert value from '%s' to integer : %w", itemTrim, err)
+ }
+ case strings.HasPrefix(itemTrimBfdLiveDet, "neighbor "):
+ confRead.parentEtherOpts[0]["bfd_liveness_detection"].([]map[string]interface{})[0]["neighbor"] =
+ strings.TrimPrefix(itemTrimBfdLiveDet, "neighbor ")
+ case itemTrimBfdLiveDet == "no-adaptation":
+ confRead.parentEtherOpts[0]["bfd_liveness_detection"].([]map[string]interface{})[0]["no_adaptation"] =
+ true
+ case strings.HasPrefix(itemTrimBfdLiveDet, "transmit-interval minimum-interval "):
+ var err error
+ confRead.parentEtherOpts[0]["bfd_liveness_detection"].([]map[string]interface{})[0]["transmit_interval_minimum_interval"], // nolint: lll
+ err = strconv.Atoi(strings.TrimPrefix(itemTrimBfdLiveDet, "transmit-interval minimum-interval "))
+ if err != nil {
+ return fmt.Errorf("failed to convert value from '%s' to integer : %w", itemTrim, err)
+ }
+ case strings.HasPrefix(itemTrimBfdLiveDet, "transmit-interval threshold "):
+ var err error
+ confRead.parentEtherOpts[0]["bfd_liveness_detection"].([]map[string]interface{})[0]["transmit_interval_threshold"],
+ err = strconv.Atoi(strings.TrimPrefix(itemTrimBfdLiveDet, "transmit-interval threshold "))
+ if err != nil {
+ return fmt.Errorf("failed to convert value from '%s' to integer : %w", itemTrim, err)
+ }
+ case strings.HasPrefix(itemTrimBfdLiveDet, "version "):
+ confRead.parentEtherOpts[0]["bfd_liveness_detection"].([]map[string]interface{})[0]["version"] =
+ strings.TrimPrefix(itemTrimBfdLiveDet, "version ")
+ }
+ case itemTrim == flowControlWords:
+ confRead.parentEtherOpts[0]["flow_control"] = true
+ case itemTrim == noFlowControlWords:
+ confRead.parentEtherOpts[0]["no_flow_control"] = true
+ case strings.HasPrefix(itemTrim, "lacp "):
+ if len(confRead.parentEtherOpts[0]["lacp"].([]map[string]interface{})) == 0 {
+ confRead.parentEtherOpts[0]["lacp"] = append(confRead.parentEtherOpts[0]["lacp"].([]map[string]interface{}),
+ map[string]interface{}{
+ "mode": "",
+ "admin_key": -1,
+ "periodic": "",
+ "sync_reset": "",
+ "system_id": "",
+ "system_priority": -1,
+ })
+ }
+ itemTrimLacp := strings.TrimPrefix(itemTrim, "lacp ")
+ switch {
+ case itemTrimLacp == activeW || itemTrimLacp == "passive":
+ confRead.parentEtherOpts[0]["lacp"].([]map[string]interface{})[0]["mode"] = itemTrimLacp
+ case strings.HasPrefix(itemTrimLacp, "admin-key "):
+ var err error
+ confRead.parentEtherOpts[0]["lacp"].([]map[string]interface{})[0]["admin_key"], err =
+ strconv.Atoi(strings.TrimPrefix(itemTrimLacp, "admin-key "))
+ if err != nil {
+ return fmt.Errorf("failed to convert value from '%s' to integer : %w", itemTrim, err)
+ }
+ case strings.HasPrefix(itemTrimLacp, "periodic "):
+ confRead.parentEtherOpts[0]["lacp"].([]map[string]interface{})[0]["periodic"] =
+ strings.TrimPrefix(itemTrimLacp, "periodic ")
+ case strings.HasPrefix(itemTrimLacp, "sync-reset "):
+ confRead.parentEtherOpts[0]["lacp"].([]map[string]interface{})[0]["sync_reset"] =
+ strings.TrimPrefix(itemTrimLacp, "sync-reset ")
+ case strings.HasPrefix(itemTrimLacp, "system-id "):
+ confRead.parentEtherOpts[0]["lacp"].([]map[string]interface{})[0]["system_id"] =
+ strings.TrimPrefix(itemTrimLacp, "system-id ")
+ case strings.HasPrefix(itemTrimLacp, "system-priority "):
+ var err error
+ confRead.parentEtherOpts[0]["lacp"].([]map[string]interface{})[0]["system_priority"], err =
+ strconv.Atoi(strings.TrimPrefix(itemTrimLacp, "system-priority "))
+ if err != nil {
+ return fmt.Errorf("failed to convert value from '%s' to integer : %w", itemTrim, err)
+ }
+ }
+ case itemTrim == loopbackWord:
+ confRead.parentEtherOpts[0]["loopback"] = true
+ case itemTrim == noLoopbackWord:
+ confRead.parentEtherOpts[0]["no_loopback"] = true
+ case strings.HasPrefix(itemTrim, "link-speed "):
+ confRead.parentEtherOpts[0]["link_speed"] = strings.TrimPrefix(itemTrim, "link-speed ")
+ case strings.HasPrefix(itemTrim, "minimum-bandwidth bw-value "):
+ confRead.parentEtherOpts[0]["minimum_bandwidth"] = strings.TrimPrefix(itemTrim, "minimum-bandwidth bw-value ") +
+ confRead.parentEtherOpts[0]["minimum_bandwidth"].(string)
+ case strings.HasPrefix(itemTrim, "minimum-bandwidth bw-unit "):
+ confRead.parentEtherOpts[0]["minimum_bandwidth"] = confRead.parentEtherOpts[0]["minimum_bandwidth"].(string) +
+ " " + strings.TrimPrefix(itemTrim, "minimum-bandwidth bw-unit ")
+ case strings.HasPrefix(itemTrim, "minimum-links "):
+ var err error
+ confRead.parentEtherOpts[0]["minimum_links"], err =
+ strconv.Atoi(strings.TrimPrefix(itemTrim, "minimum-links "))
+ if err != nil {
+ return fmt.Errorf("failed to convert value from '%s' to integer : %w", itemTrim, err)
+ }
+ case strings.HasPrefix(itemTrim, "redundancy-group "):
+ var err error
+ confRead.parentEtherOpts[0]["redundancy_group"], err =
+ strconv.Atoi(strings.TrimPrefix(itemTrim, "redundancy-group "))
+ if err != nil {
+ return fmt.Errorf("failed to convert value from '%s' to integer : %w", itemTrim, err)
+ }
+ case strings.HasPrefix(itemTrim, "source-address-filter "):
+ confRead.parentEtherOpts[0]["source_address_filter"] = append(
+ confRead.parentEtherOpts[0]["source_address_filter"].([]string),
+ strings.TrimPrefix(itemTrim, "source-address-filter "))
+ case itemTrim == "source-filtering":
+ confRead.parentEtherOpts[0]["source_filtering"] = true
+ }
+
+ return nil
+}
+
func delInterfacePhysical(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
if err := checkInterfacePhysicalContainsUnit(d.Get("name").(string), m, jnprSess); err != nil {
@@ -562,26 +1560,41 @@ func delInterfacePhysical(d *schema.ResourceData, m interface{}, jnprSess *Netco
return err
}
}
- } else if d.Get("ether802_3ad").(string) != "" {
- lastAEchild, err := interfaceAggregatedLastChild(d.Get("ether802_3ad").(string), d.Get("name").(string), m, jnprSess)
- if err != nil {
- return err
+ } else if d.Get("ether802_3ad").(string) != "" ||
+ len(d.Get("ether_opts").([]interface{})) != 0 ||
+ len(d.Get("gigether_opts").([]interface{})) != 0 {
+ var aeDel string
+ switch {
+ case d.Get("ether802_3ad").(string) != "":
+ aeDel = d.Get("ether802_3ad").(string)
+ case len(d.Get("ether_opts").([]interface{})) != 0 && d.Get("ether_opts").([]interface{})[0] != nil:
+ v := d.Get("ether_opts").([]interface{})[0].(map[string]interface{})
+ aeDel = v["ae_8023ad"].(string)
+ case len(d.Get("gigether_opts").([]interface{})) != 0 && d.Get("gigether_opts").([]interface{})[0] != nil:
+ v := d.Get("gigether_opts").([]interface{})[0].(map[string]interface{})
+ aeDel = v["ae_8023ad"].(string)
}
- if lastAEchild {
- aggregatedCount, err := interfaceAggregatedCountSearchMax("ae-1", d.Get("ether802_3ad").(string),
- d.Get("name").(string), m, jnprSess)
+ if aeDel != "" {
+ lastAEchild, err := interfaceAggregatedLastChild(aeDel, d.Get("name").(string), m, jnprSess)
if err != nil {
return err
}
- if aggregatedCount == "0" {
- err = sess.configSet([]string{"delete chassis aggregated-devices ethernet device-count"}, jnprSess)
+ if lastAEchild {
+ aggregatedCount, err := interfaceAggregatedCountSearchMax("ae-1", aeDel,
+ d.Get("name").(string), m, jnprSess)
if err != nil {
return err
}
- } else {
- err = sess.configSet([]string{"set chassis aggregated-devices ethernet device-count " + aggregatedCount}, jnprSess)
- if err != nil {
- return err
+ if aggregatedCount == "0" {
+ err = sess.configSet([]string{"delete chassis aggregated-devices ethernet device-count"}, jnprSess)
+ if err != nil {
+ return err
+ }
+ } else {
+ err = sess.configSet([]string{"set chassis aggregated-devices ethernet device-count " + aggregatedCount}, jnprSess)
+ if err != nil {
+ return err
+ }
}
}
}
@@ -614,6 +1627,7 @@ func checkInterfacePhysicalContainsUnit(interFace string, m interface{}, jnprSes
return nil
}
+
func delInterfaceNC(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
configSet := make([]string, 0, 1)
@@ -623,47 +1637,71 @@ func delInterfaceNC(d *schema.ResourceData, m interface{}, jnprSess *NetconfObje
}
configSet = append(configSet, delPrefix+"description")
configSet = append(configSet, delPrefix+"disable")
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
+
func delInterfacePhysicalOpts(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
configSet := make([]string, 0, 1)
delPrefix := "delete interfaces " + d.Get("name").(string) + " "
configSet = append(configSet,
delPrefix+"aggregated-ether-options",
- delPrefix+"ether-options 802.3ad",
- delPrefix+"gigether-options 802.3ad",
+ delPrefix+"description",
+ delPrefix+"esi",
+ delPrefix+"ether-options",
+ delPrefix+"gigether-options",
delPrefix+"native-vlan-id",
+ delPrefix+"redundant-ether-options",
delPrefix+"unit 0 family ethernet-switching interface-mode",
delPrefix+"unit 0 family ethernet-switching vlan members",
delPrefix+"vlan-tagging",
)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillInterfacePhysicalData(d *schema.ResourceData, interfaceOpt interfacePhysicalOptions) {
- if tfErr := d.Set("ae_lacp", interfaceOpt.aeLacp); tfErr != nil {
- panic(tfErr)
+ _, okAeLacp := d.GetOk("ae_lacp")
+ if okAeLacp {
+ if tfErr := d.Set("ae_lacp", interfaceOpt.aeLacp); tfErr != nil {
+ panic(tfErr)
+ }
}
- if tfErr := d.Set("ae_link_speed", interfaceOpt.aeLinkSpeed); tfErr != nil {
- panic(tfErr)
+ _, okAeLinkSpeed := d.GetOk("ae_link_speed")
+ if okAeLinkSpeed {
+ if tfErr := d.Set("ae_link_speed", interfaceOpt.aeLinkSpeed); tfErr != nil {
+ panic(tfErr)
+ }
+ }
+ _, okAeMinLinks := d.GetOk("ae_minimum_links")
+ if okAeMinLinks {
+ if tfErr := d.Set("ae_minimum_links", interfaceOpt.aeMinLink); tfErr != nil {
+ panic(tfErr)
+ }
}
- if tfErr := d.Set("ae_minimum_links", interfaceOpt.aeMinLink); tfErr != nil {
+ if tfErr := d.Set("esi", interfaceOpt.esi); tfErr != nil {
panic(tfErr)
}
if tfErr := d.Set("description", interfaceOpt.description); tfErr != nil {
panic(tfErr)
}
- if tfErr := d.Set("ether802_3ad", interfaceOpt.v8023ad); tfErr != nil {
- panic(tfErr)
+ if _, ok := d.GetOk("ether802_3ad"); ok {
+ if tfErr := d.Set("ether802_3ad", interfaceOpt.v8023ad); tfErr != nil {
+ panic(tfErr)
+ }
+ } else {
+ if tfErr := d.Set("ether_opts", interfaceOpt.etherOpts); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("gigether_opts", interfaceOpt.gigetherOpts); tfErr != nil {
+ panic(tfErr)
+ }
+ }
+ if !okAeLacp && !okAeLinkSpeed && !okAeMinLinks {
+ if tfErr := d.Set("parent_ether_opts", interfaceOpt.parentEtherOpts); tfErr != nil {
+ panic(tfErr)
+ }
}
if tfErr := d.Set("trunk", interfaceOpt.trunk); tfErr != nil {
panic(tfErr)
diff --git a/junos/resource_interface_physical_test.go b/junos/resource_interface_physical_test.go
index 7ce0335e..2403b453 100644
--- a/junos/resource_interface_physical_test.go
+++ b/junos/resource_interface_physical_test.go
@@ -1,7 +1,6 @@
package junos_test
import (
- "fmt"
"os"
"testing"
@@ -12,6 +11,7 @@ import (
// export TESTACC_INTERFACE_AE=ae for choose interface aggregate test else it's ae0.
func TestAccJunosInterfacePhysical_basic(t *testing.T) {
var testaccInterface string
+ var testaccInterface2 string
var testaccInterfaceAE string
if os.Getenv("TESTACC_INTERFACE") != "" {
testaccInterface = os.Getenv("TESTACC_INTERFACE")
@@ -23,13 +23,18 @@ func TestAccJunosInterfacePhysical_basic(t *testing.T) {
} else {
testaccInterfaceAE = "ae0"
}
+ if os.Getenv("TESTACC_INTERFACE2") != "" {
+ testaccInterface2 = os.Getenv("TESTACC_INTERFACE2")
+ } else {
+ testaccInterface2 = "ge-0/0/4"
+ }
if os.Getenv("TESTACC_SWITCH") != "" {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
- Config: testAccJunosInterfacePhysicalConfigCreate(testaccInterface),
+ Config: testAccJunosInterfacePhysicalSWConfigCreate(testaccInterface),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("junos_interface_physical.testacc_interface",
"description", "testacc_interface"),
@@ -44,7 +49,7 @@ func TestAccJunosInterfacePhysical_basic(t *testing.T) {
),
},
{
- Config: testAccJunosInterfacePhysicalConfigUpdate(testaccInterface),
+ Config: testAccJunosInterfacePhysicalSWConfigUpdate(testaccInterface),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("junos_interface_physical.testacc_interface",
"description", "testacc_interfaceU"),
@@ -66,36 +71,102 @@ func TestAccJunosInterfacePhysical_basic(t *testing.T) {
},
})
} else {
+ if os.Getenv("TESTACC_ROUTER") != "" {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ Providers: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccJunosInterfacePhysicalRouterConfigCreate(testaccInterface, testaccInterfaceAE),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("junos_interface_physical.testacc_interfaceAE",
+ "parent_ether_opts.#", "1"),
+ resource.TestCheckResourceAttr("junos_interface_physical.testacc_interfaceAE",
+ "parent_ether_opts.0.source_address_filter.#", "1"),
+ resource.TestCheckResourceAttr("junos_interface_physical.testacc_interfaceAE",
+ "parent_ether_opts.0.source_filtering", "true"),
+ resource.TestCheckResourceAttr("junos_interface_physical.testacc_interfaceAE",
+ "esi.#", "1"),
+ resource.TestCheckResourceAttr("junos_interface_physical.testacc_interfaceAE",
+ "esi.0.identifier", "00:01:11:11:11:11:11:11:11:11"),
+ resource.TestCheckResourceAttr("junos_interface_physical.testacc_interfaceAE",
+ "esi.0.mode", "all-active"),
+ ),
+ },
+ {
+ Config: testAccJunosInterfacePhysicalRouterConfigUpdate(testaccInterface, testaccInterfaceAE),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("junos_interface_physical.testacc_interfaceAE",
+ "esi.#", "1"),
+ resource.TestCheckResourceAttr("junos_interface_physical.testacc_interfaceAE",
+ "esi.0.identifier", "00:11:11:11:11:11:11:11:11:11"),
+ resource.TestCheckResourceAttr("junos_interface_physical.testacc_interfaceAE",
+ "esi.0.mode", "all-active"),
+ ),
+ },
+ {
+ ResourceName: "junos_interface_physical.testacc_interfaceAE",
+ ImportState: true,
+ ImportStateVerify: true,
+ },
+ },
+ })
+ }
+ if os.Getenv("TESTACC_SRX") != "" {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ Providers: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccJunosInterfacePhysicalSRXConfigCreate(testaccInterface, testaccInterface2),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("junos_interface_physical.testacc_interface_reth",
+ "parent_ether_opts.#", "1"),
+ resource.TestCheckResourceAttr("junos_interface_physical.testacc_interface_reth",
+ "parent_ether_opts.0.redundancy_group", "1"),
+ ),
+ },
+ },
+ })
+ }
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
- Config: testAccJunosInterfacePhysicalFWConfigCreate(testaccInterface, testaccInterfaceAE),
+ Config: testAccJunosInterfacePhysicalConfigCreate(testaccInterface, testaccInterfaceAE, testaccInterface2),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("junos_interface_physical.testacc_interface",
"description", "testacc_interface"),
resource.TestCheckResourceAttr("junos_interface_physical.testacc_interface",
- "ether802_3ad", testaccInterfaceAE),
+ "gigether_opts.#", "1"),
+ resource.TestCheckResourceAttr("junos_interface_physical.testacc_interface",
+ "gigether_opts.0.ae_8023ad", testaccInterfaceAE),
resource.TestCheckResourceAttr("junos_interface_physical.testacc_interfaceAE",
"name", testaccInterfaceAE),
resource.TestCheckResourceAttr("junos_interface_physical.testacc_interfaceAE",
- "ae_lacp", "active"),
+ "parent_ether_opts.#", "1"),
resource.TestCheckResourceAttr("junos_interface_physical.testacc_interfaceAE",
- "ae_minimum_links", "1"),
+ "parent_ether_opts.0.lacp.#", "1"),
+ resource.TestCheckResourceAttr("junos_interface_physical.testacc_interfaceAE",
+ "parent_ether_opts.0.lacp.0.mode", "active"),
+ resource.TestCheckResourceAttr("junos_interface_physical.testacc_interfaceAE",
+ "parent_ether_opts.0.minimum_links", "1"),
resource.TestCheckResourceAttr("junos_interface_physical.testacc_interfaceAE",
"vlan_tagging", "true"),
),
},
{
- Config: testAccJunosInterfacePhysicalFWConfigUpdate(testaccInterface, testaccInterfaceAE),
+ Config: testAccJunosInterfacePhysicalConfigUpdate(testaccInterface, testaccInterfaceAE, testaccInterface2),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("junos_interface_physical.testacc_interface",
"description", "testacc_interfaceU"),
resource.TestCheckResourceAttr("junos_interface_physical.testacc_interfaceAE",
- "ae_lacp", ""),
+ "parent_ether_opts.#", "1"),
resource.TestCheckResourceAttr("junos_interface_physical.testacc_interfaceAE",
- "ae_minimum_links", "0"),
+ "parent_ether_opts.0.lacp.#", "0"),
+ resource.TestCheckResourceAttr("junos_interface_physical.testacc_interfaceAE",
+ "parent_ether_opts.0.minimum_bandwidth", "1 gbps"),
),
},
{
@@ -108,13 +179,16 @@ func TestAccJunosInterfacePhysical_basic(t *testing.T) {
ImportState: true,
ImportStateVerify: true,
},
+ {
+ Config: testAccJunosInterfacePhysicalConfigUpdate2(testaccInterface, testaccInterfaceAE),
+ },
},
})
}
}
-func testAccJunosInterfacePhysicalConfigCreate(interFace string) string {
- return fmt.Sprintf(`
+func testAccJunosInterfacePhysicalSWConfigCreate(interFace string) string {
+ return `
resource junos_interface_physical testacc_interface {
name = "` + interFace + `"
description = "testacc_interface"
@@ -122,45 +196,209 @@ resource junos_interface_physical testacc_interface {
vlan_native = 100
vlan_members = ["100-110"]
}
-`)
+`
}
-func testAccJunosInterfacePhysicalConfigUpdate(interFace string) string {
- return fmt.Sprintf(`
+func testAccJunosInterfacePhysicalSWConfigUpdate(interFace string) string {
+ return `
resource junos_interface_physical testacc_interface {
name = "` + interFace + `"
description = "testacc_interfaceU"
vlan_members = ["100"]
}
-`)
+`
}
-func testAccJunosInterfacePhysicalFWConfigCreate(interFace, interfaceAE string) string {
- return fmt.Sprintf(`
+func testAccJunosInterfacePhysicalConfigCreate(interFace, interfaceAE, interFace2 string) string {
+ return `
resource junos_interface_physical testacc_interface {
- name = "` + interFace + `"
- description = "testacc_interface"
- ether802_3ad = "` + interfaceAE + `"
+ name = "` + interFace + `"
+ description = "testacc_interface"
+ gigether_opts {
+ ae_8023ad = "` + interfaceAE + `"
+ }
}
-resource junos_interface_physical testacc_interfaceAE {
- name = junos_interface_physical.testacc_interface.ether802_3ad
- description = "testacc_interfaceAE"
- ae_lacp = "active"
- ae_minimum_links = 1
- vlan_tagging = true
+resource junos_interface_physical testacc_interface2 {
+ name = "` + interFace2 + `"
+ description = "testacc_interface2"
+ gigether_opts {
+ flow_control = true
+ loopback = true
+ auto_negotiation = true
+ }
+}
+resource "junos_interface_physical" "testacc_interfaceAE" {
+ depends_on = [
+ junos_interface_physical.testacc_interface,
+ ]
+ name = "` + interfaceAE + `"
+ description = "testacc_interfaceAE"
+ parent_ether_opts {
+ flow_control = true
+ lacp {
+ mode = "active"
+ admin_key = 1
+ periodic = "slow"
+ sync_reset = "disable"
+ system_id = "00:00:01:00:01:00"
+ system_priority = 250
+ }
+ loopback = true
+ link_speed = "1g"
+ minimum_links = 1
+ }
+ vlan_tagging = true
}
-`)
+`
}
-func testAccJunosInterfacePhysicalFWConfigUpdate(interFace, interfaceAE string) string {
- return fmt.Sprintf(`
+func testAccJunosInterfacePhysicalConfigUpdate(interFace, interfaceAE, interFace2 string) string {
+ return `
resource junos_interface_physical testacc_interface {
- name = "` + interFace + `"
- description = "testacc_interfaceU"
- ether802_3ad = "` + interfaceAE + `"
+ name = "` + interFace + `"
+ description = "testacc_interfaceU"
+ gigether_opts {
+ ae_8023ad = "` + interfaceAE + `"
+ }
+}
+resource junos_interface_physical testacc_interface2 {
+ name = "` + interFace2 + `"
+ description = "testacc_interface2"
+ ether_opts {
+ flow_control = true
+ loopback = true
+ auto_negotiation = true
+ }
+}
+resource "junos_interface_logical" "testacc_interfaceLO" {
+ name = "lo0.0"
+ family_inet {
+ address {
+ cidr_ip = "192.0.2.1/32"
+ }
+ }
}
-resource junos_interface_physical testacc_interfaceAE {
- name = junos_interface_physical.testacc_interface.ether802_3ad
- description = "testacc_interfaceAE"
+resource "junos_interface_physical" "testacc_interfaceAE" {
+ depends_on = [
+ junos_interface_physical.testacc_interface,
+ junos_interface_logical.testacc_interfaceLO,
+ ]
+ name = "` + interfaceAE + `"
+ description = "testacc_interfaceAE"
+ parent_ether_opts {
+ bfd_liveness_detection {
+ local_address = "192.0.2.1"
+ detection_time_threshold = 30
+ holddown_interval = 30
+ minimum_interval = 30
+ minimum_receive_interval = 10
+ multiplier = 1
+ neighbor = "192.0.2.2"
+ no_adaptation = true
+ transmit_interval_minimum_interval = 10
+ transmit_interval_threshold = 30
+ version = "automatic"
+ }
+ no_flow_control = true
+ no_loopback = true
+ link_speed = "1g"
+ minimum_bandwidth = "1 gbps"
+ }
vlan_tagging = true
}
-`)
+`
+}
+func testAccJunosInterfacePhysicalConfigUpdate2(interFace, interfaceAE string) string {
+ return `
+resource junos_interface_physical testacc_interface {
+ name = "` + interFace + `"
+ description = "testacc_interfaceU"
+ ether_opts {
+ ae_8023ad = "` + interfaceAE + `"
+ }
+}
+`
+}
+
+func testAccJunosInterfacePhysicalRouterConfigCreate(interFace, interfaceAE string) string {
+ return `
+resource "junos_interface_physical" "testacc_interface" {
+ name = "` + interFace + `"
+ description = "testacc_interface"
+ gigether_opts {
+ ae_8023ad = "` + interfaceAE + `"
+ }
+}
+resource "junos_interface_physical" "testacc_interfaceAE" {
+ name = "` + interfaceAE + `"
+ description = "testacc_interfaceAE"
+ esi {
+ identifier = "00:01:11:11:11:11:11:11:11:11"
+ mode = "all-active"
+ }
+ parent_ether_opts {
+ source_address_filter = ["00:11:22:33:44:55"]
+ source_filtering = true
+ }
+ vlan_tagging = true
+}
+`
+}
+func testAccJunosInterfacePhysicalRouterConfigUpdate(interFace, interfaceAE string) string {
+ return `
+resource "junos_interface_physical" "testacc_interface" {
+ name = "` + interFace + `"
+ description = "testacc_interface"
+ gigether_opts {
+ ae_8023ad = "` + interfaceAE + `"
+ }
+}
+resource "junos_interface_physical" "testacc_interfaceAE" {
+ name = "` + interfaceAE + `"
+ description = "testacc_interfaceAE"
+ esi {
+ identifier = "00:11:11:11:11:11:11:11:11:11"
+ mode = "all-active"
+ }
+ vlan_tagging = true
+}
+`
+}
+
+func testAccJunosInterfacePhysicalSRXConfigCreate(interFace, interFace2 string) string {
+ return `
+resource "junos_interface_physical" "testacc_interface" {
+ depends_on = [
+ junos_chassis_cluster.testacc_interface
+ ]
+ name = "` + interFace + `"
+ description = "testacc_interface"
+ gigether_opts {
+ redundant_parent = "reth0"
+ }
+}
+resource "junos_chassis_cluster" "testacc_interface" {
+ fab0 {
+ member_interfaces = ["` + interFace2 + `"]
+ }
+ redundancy_group {
+ node0_priority = 100
+ node1_priority = 99
+ }
+ redundancy_group {
+ node0_priority = 100
+ node1_priority = 99
+ }
+ reth_count = 1
+}
+resource "junos_interface_physical" "testacc_interface_reth" {
+ depends_on = [
+ junos_interface_physical.testacc_interface
+ ]
+ name = "reth0"
+ description = "testacc_interface_reth"
+ parent_ether_opts {
+ redundancy_group = 1
+ minimum_links = 1
+ }
+}
+`
}
diff --git a/junos/resource_interface_st0_unit.go b/junos/resource_interface_st0_unit.go
index 516575ee..0ac3d1e8 100644
--- a/junos/resource_interface_st0_unit.go
+++ b/junos/resource_interface_st0_unit.go
@@ -33,7 +33,7 @@ func resourceInterfaceSt0UnitCreate(ctx context.Context, d *schema.ResourceData,
if err != nil {
sess.configClear(jnprSess)
- return diag.FromErr(fmt.Errorf("error for find new st0 unit interface: %w", err))
+ return diag.FromErr(fmt.Errorf("error for find new st0 unit interface : %w", err))
}
if err := sess.configSet([]string{"set interfaces " + newSt0}, jnprSess); err != nil {
sess.configClear(jnprSess)
diff --git a/junos/resource_null_commit_file.go b/junos/resource_null_commit_file.go
new file mode 100644
index 00000000..2649f996
--- /dev/null
+++ b/junos/resource_null_commit_file.go
@@ -0,0 +1,122 @@
+package junos
+
+import (
+ "context"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "strings"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func resourceNullCommitFile() *schema.Resource {
+ return &schema.Resource{
+ CreateContext: resourceNullCommitFileCreate,
+ ReadContext: resourceNullCommitFileRead,
+ DeleteContext: resourceNullCommitFileDelete,
+ Schema: map[string]*schema.Schema{
+ "filename": {
+ Type: schema.TypeString,
+ Required: true,
+ ForceNew: true,
+ },
+ "append_lines": {
+ Type: schema.TypeList,
+ ForceNew: true,
+ Optional: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ "clear_file_after_commit": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ForceNew: true,
+ },
+ "triggers": {
+ Type: schema.TypeMap,
+ Optional: true,
+ ForceNew: true,
+ },
+ },
+ }
+}
+
+func resourceNullCommitFileCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ sess := m.(*Session)
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ defer sess.closeSession(jnprSess)
+ sess.configLock(jnprSess)
+ fileName := d.Get("filename").(string)
+ configSet, err := readNullCommitFile(fileName)
+ if err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ for _, v := range d.Get("append_lines").([]interface{}) {
+ configSet = append(configSet, v.(string))
+ }
+ if err := sess.configSet(configSet, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ var diagWarns diag.Diagnostics
+ warns, err := sess.commitConf("commit a file with resource junos_null_commit_file", jnprSess)
+ appendDiagWarns(&diagWarns, warns)
+ if err != nil {
+ sess.configClear(jnprSess)
+
+ return append(diagWarns, diag.FromErr(err)...)
+ }
+ d.SetId(fileName)
+ if d.Get("clear_file_after_commit").(bool) {
+ if err := cleanNullCommitFile(fileName, sess); err != nil {
+ return append(diagWarns, diag.FromErr(err)...)
+ }
+ }
+
+ return diagWarns
+}
+func resourceNullCommitFileRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ return nil
+}
+func resourceNullCommitFileDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ d.SetId("")
+
+ return nil
+}
+
+func readNullCommitFile(filename string) ([]string, error) {
+ if err := replaceTildeToHomeDir(&filename); err != nil {
+ return []string{}, err
+ }
+ _, err := os.Stat(filename)
+ if os.IsNotExist(err) {
+ return []string{}, fmt.Errorf("file `%s` doesn't exist", filename)
+ }
+ fileReadByte, err := ioutil.ReadFile(filename)
+ if err != nil {
+ return []string{}, fmt.Errorf("could not read file `%s` : %w", filename, err)
+ }
+
+ return strings.Split(string(fileReadByte), "\n"), nil
+}
+func cleanNullCommitFile(filename string, sess *Session) error {
+ if err := replaceTildeToHomeDir(&filename); err != nil {
+ return err
+ }
+ f, err := os.OpenFile(filename, os.O_TRUNC, os.FileMode(sess.junosFilePermission))
+ if err != nil {
+ return fmt.Errorf("could not open file `%s` to truncate after commit : %w", filename, err)
+ }
+ if err := f.Close(); err != nil {
+ return fmt.Errorf("could not close file handler for `%s` after truncation : %w", filename, err)
+ }
+
+ return nil
+}
diff --git a/junos/resource_null_commit_file_test.go b/junos/resource_null_commit_file_test.go
new file mode 100644
index 00000000..1b4ce909
--- /dev/null
+++ b/junos/resource_null_commit_file_test.go
@@ -0,0 +1,85 @@
+package junos_test
+
+import (
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+)
+
+const testaccNullCommitFile = "/tmp/testacc/terraform-provider-junos/null-commit-file"
+
+func TestAccJunosNullCommitFile_basic(t *testing.T) {
+ var testaccInterface string
+ if os.Getenv("TESTACC_INTERFACE") != "" {
+ testaccInterface = os.Getenv("TESTACC_INTERFACE")
+ } else {
+ testaccInterface = defaultInterfaceTestAcc
+ }
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ Providers: testAccProviders,
+ ExternalProviders: map[string]resource.ExternalProvider{
+ "local": {},
+ },
+ Steps: []resource.TestStep{
+ {
+ Config: testAccJunosNullCommitFilePreCreate(testaccInterface),
+ },
+ {
+ Config: testAccJunosNullCommitFileCreate(testaccInterface),
+ ExpectNonEmptyPlan: true,
+ },
+ {
+ Config: testAccJunosNullCommitFileRead(testaccInterface),
+ PlanOnly: true,
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("junos_interface_physical.testacc_nullcommitfile",
+ "description", "testacc_nullfile"),
+ resource.TestCheckResourceAttr("data.junos_interface_physical.testacc_nullcommitfile",
+ "description", "testacc_nullfile"),
+ ),
+ ExpectNonEmptyPlan: true,
+ },
+ },
+ })
+}
+
+func testAccJunosNullCommitFilePreCreate(interFace string) string {
+ return `
+resource junos_interface_physical testacc_nullcommitfile {
+ name = "` + interFace + `"
+ description = "testacc_null"
+ vlan_tagging = true
+}
+`
+}
+func testAccJunosNullCommitFileCreate(interFace string) string {
+ return `
+resource junos_interface_physical testacc_nullcommitfile {
+ name = "` + interFace + `"
+ description = "testacc_null"
+ vlan_tagging = true
+}
+resource "local_file" "hostname" {
+ content = "set interfaces ` + interFace + ` description testacc_nullfile"
+ filename = "` + testaccNullCommitFile + `"
+}
+resource junos_null_commit_file "testacc_nullcommitfile" {
+ filename = local_file.hostname.filename
+ clear_file_after_commit = true
+}
+`
+}
+func testAccJunosNullCommitFileRead(interFace string) string {
+ return `
+resource junos_interface_physical testacc_nullcommitfile {
+ name = "` + interFace + `"
+ description = "testacc_null"
+ vlan_tagging = true
+}
+data junos_interface_physical testacc_nullcommitfile {
+ config_interface = "` + interFace + `"
+}
+`
+}
diff --git a/junos/resource_ospf_area.go b/junos/resource_ospf_area.go
index 6412277c..44771b34 100644
--- a/junos/resource_ospf_area.go
+++ b/junos/resource_ospf_area.go
@@ -38,7 +38,7 @@ func resourceOspfArea() *schema.Resource {
Optional: true,
ForceNew: true,
Default: defaultWord,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"version": {
Type: schema.TypeString,
@@ -93,6 +93,15 @@ func resourceOspfArea() *schema.Resource {
func resourceOspfAreaCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setOspfArea(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("area_id").(string) + idSeparator + d.Get("version").(string) +
+ idSeparator + d.Get("routing_instance").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -320,11 +329,8 @@ func setOspfArea(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject)
strconv.Itoa(ospfInterface["retransmit_interval"].(int)))
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readOspfArea(idArea, version, routingInstance string,
m interface{}, jnprSess *NetconfObject) (ospfAreaOptions, error) {
@@ -426,11 +432,8 @@ func delOspfArea(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject)
configSet = append(configSet, "delete routing-instances "+d.Get("routing_instance").(string)+
" protocols "+ospfVersion+" area "+d.Get("area_id").(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillOspfAreaData(d *schema.ResourceData, ospfAreaOptions ospfAreaOptions) {
diff --git a/junos/resource_policyoptions_as_path.go b/junos/resource_policyoptions_as_path.go
index b2463ade..8943b5f1 100644
--- a/junos/resource_policyoptions_as_path.go
+++ b/junos/resource_policyoptions_as_path.go
@@ -29,7 +29,7 @@ func resourcePolicyoptionsAsPath() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"dynamic_db": {
Type: schema.TypeBool,
@@ -45,6 +45,14 @@ func resourcePolicyoptionsAsPath() *schema.Resource {
func resourcePolicyoptionsAsPathCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setPolicyoptionsAsPath(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -221,11 +229,8 @@ func setPolicyoptionsAsPath(d *schema.ResourceData, m interface{}, jnprSess *Net
configSet = append(configSet, "set policy-options as-path "+d.Get("name").(string)+
" \""+d.Get("path").(string)+"\"")
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readPolicyoptionsAsPath(asPath string, m interface{}, jnprSess *NetconfObject) (asPathOptions, error) {
sess := m.(*Session)
@@ -262,11 +267,8 @@ func delPolicyoptionsAsPath(asPath string, m interface{}, jnprSess *NetconfObjec
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete policy-options as-path "+asPath)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillPolicyoptionsAsPathData(d *schema.ResourceData, asPathOptions asPathOptions) {
if tfErr := d.Set("name", asPathOptions.name); tfErr != nil {
diff --git a/junos/resource_policyoptions_as_path_group.go b/junos/resource_policyoptions_as_path_group.go
index 26a971d1..c66cd838 100644
--- a/junos/resource_policyoptions_as_path_group.go
+++ b/junos/resource_policyoptions_as_path_group.go
@@ -29,7 +29,7 @@ func resourcePolicyoptionsAsPathGroup() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"as_path": {
Type: schema.TypeList,
@@ -39,7 +39,7 @@ func resourcePolicyoptionsAsPathGroup() *schema.Resource {
"name": {
Type: schema.TypeString,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"path": {
Type: schema.TypeString,
@@ -59,6 +59,14 @@ func resourcePolicyoptionsAsPathGroup() *schema.Resource {
func resourcePolicyoptionsAsPathGroupCreate(
ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setPolicyoptionsAsPathGroup(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -240,11 +248,8 @@ func setPolicyoptionsAsPathGroup(d *schema.ResourceData, m interface{}, jnprSess
if d.Get("dynamic_db").(bool) {
configSet = append(configSet, setPrefix+" dynamic-db")
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readPolicyoptionsAsPathGroup(asPathGroup string,
m interface{}, jnprSess *NetconfObject) (asPathGroupOptions, error) {
@@ -290,11 +295,8 @@ func delPolicyoptionsAsPathGroup(asPathGroup string, m interface{}, jnprSess *Ne
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete policy-options as-path-group "+asPathGroup)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillPolicyoptionsAsPathGroupData(d *schema.ResourceData, asPathGroupOptions asPathGroupOptions) {
if tfErr := d.Set("name", asPathGroupOptions.name); tfErr != nil {
diff --git a/junos/resource_policyoptions_community.go b/junos/resource_policyoptions_community.go
index 1cdb50f9..50ec9876 100644
--- a/junos/resource_policyoptions_community.go
+++ b/junos/resource_policyoptions_community.go
@@ -29,7 +29,7 @@ func resourcePolicyoptionsCommunity() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"members": {
Type: schema.TypeList,
@@ -47,6 +47,14 @@ func resourcePolicyoptionsCommunity() *schema.Resource {
func resourcePolicyoptionsCommunityCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setPolicyoptionsCommunity(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -222,11 +230,8 @@ func setPolicyoptionsCommunity(d *schema.ResourceData, m interface{}, jnprSess *
if d.Get("invert_match").(bool) {
configSet = append(configSet, setPrefix+"invert-match")
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readPolicyoptionsCommunity(community string, m interface{}, jnprSess *NetconfObject) (communityOptions, error) {
sess := m.(*Session)
@@ -263,11 +268,8 @@ func delPolicyoptionsCommunity(community string, m interface{}, jnprSess *Netcon
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete policy-options community "+community)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillPolicyoptionsCommunityData(d *schema.ResourceData, communityOptions communityOptions) {
if tfErr := d.Set("name", communityOptions.name); tfErr != nil {
diff --git a/junos/resource_policyoptions_policy_statement.go b/junos/resource_policyoptions_policy_statement.go
index 6c0b73d8..cafc2593 100644
--- a/junos/resource_policyoptions_policy_statement.go
+++ b/junos/resource_policyoptions_policy_statement.go
@@ -33,7 +33,7 @@ func resourcePolicyoptionsPolicyStatement() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"from": {
Type: schema.TypeList,
@@ -69,7 +69,7 @@ func resourcePolicyoptionsPolicyStatement() *schema.Resource {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
- "inet", "inet-mdt", "inet-mvpn", "inet-vpn",
+ "evpn", "inet", "inet-mdt", "inet-mvpn", "inet-vpn",
"inet6", "inet6-mvpn", "inet6-vpn",
"iso"}, false),
},
@@ -296,7 +296,7 @@ func resourcePolicyoptionsPolicyStatement() *schema.Resource {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
- "inet", "inet-mdt", "inet-mvpn", "inet-vpn",
+ "evpn", "inet", "inet-mdt", "inet-mvpn", "inet-vpn",
"inet6", "inet6-mvpn", "inet6-vpn",
"iso"}, false),
},
@@ -356,7 +356,7 @@ func resourcePolicyoptionsPolicyStatement() *schema.Resource {
"name": {
Type: schema.TypeString,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"from": {
Type: schema.TypeList,
@@ -392,7 +392,7 @@ func resourcePolicyoptionsPolicyStatement() *schema.Resource {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
- "inet", "inet-mdt", "inet-mvpn", "inet-vpn",
+ "evpn", "inet", "inet-mdt", "inet-mvpn", "inet-vpn",
"inet6", "inet6-mvpn", "inet6-vpn",
"iso"}, false),
},
@@ -619,7 +619,7 @@ func resourcePolicyoptionsPolicyStatement() *schema.Resource {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
- "inet", "inet-mdt", "inet-mvpn", "inet-vpn",
+ "evpn", "inet", "inet-mdt", "inet-mvpn", "inet-vpn",
"inet6", "inet6-mvpn", "inet6-vpn",
"iso"}, false),
},
@@ -681,6 +681,14 @@ func resourcePolicyoptionsPolicyStatement() *schema.Resource {
func resourcePolicyoptionsPolicyStatementCreate(
ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setPolicyStatement(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -895,11 +903,7 @@ func setPolicyStatement(d *schema.ResourceData, m interface{}, jnprSess *Netconf
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readPolicyStatement(policyStatement string,
m interface{}, jnprSess *NetconfObject) (policyStatementOptions, error) {
@@ -979,11 +983,8 @@ func delPolicyStatement(policyStatement string, m interface{}, jnprSess *Netconf
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete policy-options policy-statement "+policyStatement)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillPolicyStatementData(d *schema.ResourceData, policyStatementOptions policyStatementOptions) {
if tfErr := d.Set("name", policyStatementOptions.name); tfErr != nil {
diff --git a/junos/resource_policyoptions_prefix_list.go b/junos/resource_policyoptions_prefix_list.go
index 04e962b5..25359eab 100644
--- a/junos/resource_policyoptions_prefix_list.go
+++ b/junos/resource_policyoptions_prefix_list.go
@@ -30,7 +30,7 @@ func resourcePolicyoptionsPrefixList() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"apply_path": {
Type: schema.TypeString,
@@ -41,7 +41,7 @@ func resourcePolicyoptionsPrefixList() *schema.Resource {
Optional: true,
},
"prefix": {
- Type: schema.TypeList,
+ Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
@@ -52,6 +52,14 @@ func resourcePolicyoptionsPrefixList() *schema.Resource {
func resourcePolicyoptionsPrefixListCreate(
ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setPolicyoptionsPrefixList(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -233,7 +241,7 @@ func setPolicyoptionsPrefixList(d *schema.ResourceData, m interface{}, jnprSess
if d.Get("dynamic_db").(bool) {
configSet = append(configSet, setPrefix+" dynamic-db")
}
- for _, v := range d.Get("prefix").([]interface{}) {
+ for _, v := range d.Get("prefix").(*schema.Set).List() {
err := validateCIDRNetwork(v.(string))
if err != nil {
return err
@@ -241,11 +249,7 @@ func setPolicyoptionsPrefixList(d *schema.ResourceData, m interface{}, jnprSess
configSet = append(configSet, setPrefix+" "+v.(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readPolicyoptionsPrefixList(prefixList string, m interface{}, jnprSess *NetconfObject) (prefixListOptions, error) {
sess := m.(*Session)
@@ -286,11 +290,8 @@ func delPolicyoptionsPrefixList(prefixList string, m interface{}, jnprSess *Netc
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete policy-options prefix-list "+prefixList)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillPolicyoptionsPrefixListData(d *schema.ResourceData, prefixListOptions prefixListOptions) {
if tfErr := d.Set("name", prefixListOptions.name); tfErr != nil {
diff --git a/junos/resource_rib_group.go b/junos/resource_rib_group.go
index a22e063b..86283fbd 100644
--- a/junos/resource_rib_group.go
+++ b/junos/resource_rib_group.go
@@ -30,7 +30,7 @@ func resourceRibGroup() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"import_policy": {
Type: schema.TypeList,
@@ -55,6 +55,14 @@ func resourceRibGroupCreate(ctx context.Context, d *schema.ResourceData, m inter
return diag.FromErr(err)
}
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setRibGroup(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -251,11 +259,8 @@ func setRibGroup(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject)
if d.Get("export_rib").(string) != "" {
configSet = append(configSet, setPrefix+"export-rib "+d.Get("export_rib").(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readRibGroup(group string, m interface{}, jnprSess *NetconfObject) (ribGroupOptions, error) {
sess := m.(*Session)
@@ -293,21 +298,15 @@ func delRibGroupElement(element string, group string, m interface{}, jnprSess *N
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete routing-options rib-groups "+group+" "+element)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func delRibGroup(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete routing-options rib-groups "+d.Get("name").(string))
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func validateRibGroup(d *schema.ResourceData) error {
diff --git a/junos/resource_routing_instance.go b/junos/resource_routing_instance.go
index a5458351..085e2b5a 100644
--- a/junos/resource_routing_instance.go
+++ b/junos/resource_routing_instance.go
@@ -29,7 +29,7 @@ func resourceRoutingInstance() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{"default"}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{"default"}, 64, FormatDefault),
},
"type": {
Type: schema.TypeString,
@@ -46,6 +46,14 @@ func resourceRoutingInstance() *schema.Resource {
func resourceRoutingInstanceCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setRoutingInstance(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -222,11 +230,8 @@ func setRoutingInstance(d *schema.ResourceData, m interface{}, jnprSess *Netconf
configSet = append(configSet, setPrefix+
"routing-options autonomous-system "+d.Get("as").(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readRoutingInstance(instance string, m interface{}, jnprSess *NetconfObject) (instanceOptions, error) {
sess := m.(*Session)
@@ -265,21 +270,15 @@ func delRoutingInstanceOpts(d *schema.ResourceData, m interface{}, jnprSess *Net
configSet = append(configSet,
setPrefix+"instance-type",
setPrefix+"routing-options autonomous-system")
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func delRoutingInstance(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete routing-instances "+d.Get("name").(string))
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillRoutingInstanceData(d *schema.ResourceData, instanceOptions instanceOptions) {
diff --git a/junos/resource_routing_options.go b/junos/resource_routing_options.go
index fc5517a6..392f3873 100644
--- a/junos/resource_routing_options.go
+++ b/junos/resource_routing_options.go
@@ -72,6 +72,14 @@ func resourceRoutingOptions() *schema.Resource {
func resourceRoutingOptionsCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setRoutingOptions(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId("routing_options")
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -201,11 +209,7 @@ func setRoutingOptions(d *schema.ResourceData, m interface{}, jnprSess *NetconfO
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func delRoutingOptions(m interface{}, jnprSess *NetconfObject) error {
@@ -220,11 +224,8 @@ func delRoutingOptions(m interface{}, jnprSess *NetconfObject) error {
configSet = append(configSet,
delPrefix+line)
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readRoutingOptions(m interface{}, jnprSess *NetconfObject) (routingOptionsOptions, error) {
sess := m.(*Session)
diff --git a/junos/resource_security.go b/junos/resource_security.go
index 0544b62a..2ce86a73 100644
--- a/junos/resource_security.go
+++ b/junos/resource_security.go
@@ -576,6 +576,32 @@ func resourceSecurity() *schema.Resource {
"juniper-enhanced", "juniper-local", "web-filtering-none", "websense-redirect",
}, false),
},
+ "feature_profile_web_filtering_juniper_enhanced_server": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "host": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "port": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(1, 65535),
+ },
+ "proxy_profile": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "routing_instance": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ },
+ },
+ },
},
},
},
@@ -585,6 +611,14 @@ func resourceSecurity() *schema.Resource {
func resourceSecurityCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSecurity(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId("security")
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -735,15 +769,33 @@ func setSecurity(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject)
configSet = append(configSet, setPrefix+"utm feature-profile web-filtering type "+
utm["feature_profile_web_filtering_type"].(string))
}
+ for _, v2 := range utm["feature_profile_web_filtering_juniper_enhanced_server"].([]interface{}) {
+ configSet = append(configSet, setPrefix+"utm feature-profile web-filtering juniper-enhanced server")
+ if v2 != nil {
+ utmJnpEnhServer := v2.(map[string]interface{})
+ if v3 := utmJnpEnhServer["host"].(string); v3 != "" {
+ configSet = append(configSet, setPrefix+"utm feature-profile web-filtering juniper-enhanced server host "+v3)
+ }
+ if v3 := utmJnpEnhServer["port"].(int); v3 != 0 {
+ configSet = append(configSet,
+ setPrefix+"utm feature-profile web-filtering juniper-enhanced server port "+strconv.Itoa(v3))
+ }
+ if v3 := utmJnpEnhServer["proxy_profile"].(string); v3 != "" {
+ configSet = append(configSet,
+ setPrefix+"utm feature-profile web-filtering juniper-enhanced server proxy-profile \""+v3+"\"")
+ }
+ if v3 := utmJnpEnhServer["routing_instance"].(string); v3 != "" {
+ configSet = append(configSet,
+ setPrefix+"utm feature-profile web-filtering juniper-enhanced server routing-instance "+v3)
+ }
+ }
+ }
} else {
return fmt.Errorf("utm block is empty")
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func setSecurityAlg(alg interface{}) ([]string, error) {
@@ -1212,6 +1264,7 @@ func listLinesSecurityLog() []string {
func listLinesSecurityUtm() []string {
return []string{
"utm feature-profile web-filtering type",
+ "utm feature-profile web-filtering juniper-enhanced server",
}
}
@@ -1231,11 +1284,8 @@ func delSecurity(m interface{}, jnprSess *NetconfObject) error {
configSet = append(configSet,
delPrefix+line)
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readSecurity(m interface{}, jnprSess *NetconfObject) (securityOptions, error) {
sess := m.(*Session)
@@ -1277,14 +1327,9 @@ func readSecurity(m interface{}, jnprSess *NetconfObject) (securityOptions, erro
return confRead, err
}
case checkStringHasPrefixInList(itemTrim, listLinesSecurityUtm()):
- if len(confRead.utm) == 0 {
- confRead.utm = append(confRead.utm, map[string]interface{}{
- "feature_profile_web_filtering_type": "",
- })
- }
- if strings.HasPrefix(itemTrim, "utm feature-profile web-filtering type ") {
- confRead.utm[0]["feature_profile_web_filtering_type"] = strings.TrimPrefix(itemTrim,
- "utm feature-profile web-filtering type ")
+ err := readSecurityUtm(&confRead, itemTrim)
+ if err != nil {
+ return confRead, err
}
}
}
@@ -1809,6 +1854,52 @@ func readSecurityLog(confRead *securityOptions, itemTrimLog string) error {
return nil
}
+func readSecurityUtm(confRead *securityOptions, itemTrimUtm string) error {
+ if len(confRead.utm) == 0 {
+ confRead.utm = append(confRead.utm, map[string]interface{}{
+ "feature_profile_web_filtering_type": "",
+ "feature_profile_web_filtering_juniper_enhanced_server": make([]map[string]interface{}, 0),
+ })
+ }
+ switch {
+ case strings.HasPrefix(itemTrimUtm, "utm feature-profile web-filtering type "):
+ confRead.utm[0]["feature_profile_web_filtering_type"] = strings.TrimPrefix(itemTrimUtm,
+ "utm feature-profile web-filtering type ")
+ case strings.HasPrefix(itemTrimUtm, "utm feature-profile web-filtering juniper-enhanced server"):
+ if len(confRead.utm[0]["feature_profile_web_filtering_juniper_enhanced_server"].([]map[string]interface{})) == 0 {
+ confRead.utm[0]["feature_profile_web_filtering_juniper_enhanced_server"] = append(
+ confRead.utm[0]["feature_profile_web_filtering_juniper_enhanced_server"].([]map[string]interface{}),
+ map[string]interface{}{
+ "host": "",
+ "port": 0,
+ "proxy_profile": "",
+ "routing_instance": "",
+ })
+ }
+ itemTrimServer := strings.TrimPrefix(itemTrimUtm, "utm feature-profile web-filtering juniper-enhanced server")
+ switch {
+ case strings.HasPrefix(itemTrimServer, " host "):
+ confRead.utm[0]["feature_profile_web_filtering_juniper_enhanced_server"].([]map[string]interface{})[0]["host"] =
+ strings.TrimPrefix(itemTrimServer, " host ")
+ case strings.HasPrefix(itemTrimServer, " port "):
+ var err error
+ confRead.utm[0]["feature_profile_web_filtering_juniper_enhanced_server"].([]map[string]interface{})[0]["port"], err =
+ strconv.Atoi(strings.TrimPrefix(itemTrimServer, " port "))
+ if err != nil {
+ return fmt.Errorf("failed to convert value from '%s' to integer : %w", itemTrimUtm, err)
+ }
+ case strings.HasPrefix(itemTrimServer, " proxy-profile "):
+ confRead.utm[0]["feature_profile_web_filtering_juniper_enhanced_server"].([]map[string]interface{})[0]["proxy_profile"] = //nolint: lll
+ strings.Trim(strings.TrimPrefix(itemTrimServer, " proxy-profile "), "\"")
+ case strings.HasPrefix(itemTrimServer, " routing-instance "):
+ confRead.utm[0]["feature_profile_web_filtering_juniper_enhanced_server"].([]map[string]interface{})[0]["routing_instance"] = //nolint: lll
+ strings.TrimPrefix(itemTrimServer, " routing-instance ")
+ }
+ }
+
+ return nil
+}
+
func fillSecurity(d *schema.ResourceData, securityOptions securityOptions) {
if tfErr := d.Set("alg", securityOptions.alg); tfErr != nil {
panic(tfErr)
diff --git a/junos/resource_security_address_book.go b/junos/resource_security_address_book.go
new file mode 100644
index 00000000..3b12738e
--- /dev/null
+++ b/junos/resource_security_address_book.go
@@ -0,0 +1,542 @@
+package junos
+
+import (
+ "context"
+ "fmt"
+ "strings"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
+)
+
+type addressBookOptions struct {
+ name string
+ description string
+ attachZone []string
+ networkAddress []map[string]interface{}
+ wildcardAddress []map[string]interface{}
+ dnsName []map[string]interface{}
+ rangeAddress []map[string]interface{}
+ addressSet []map[string]interface{}
+}
+
+func resourceSecurityAddressBook() *schema.Resource {
+ return &schema.Resource{
+ CreateContext: resourceSecurityAddressBookCreate,
+ ReadContext: resourceSecurityAddressBookRead,
+ UpdateContext: resourceSecurityAddressBookUpdate,
+ DeleteContext: resourceSecurityAddressBookDelete,
+ Importer: &schema.ResourceImporter{
+ State: resourceSecurityAddressBookImport,
+ },
+ Schema: map[string]*schema.Schema{
+ "name": {
+ Type: schema.TypeString,
+ Optional: true,
+ ForceNew: true,
+ Default: "global",
+ },
+ "description": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "attach_zone": {
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ "network_address": {
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "name": {
+ Type: schema.TypeString,
+ Required: true,
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatAddressName),
+ },
+ "description": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "value": {
+ Type: schema.TypeString,
+ Required: true,
+ ValidateFunc: validation.IsCIDRNetwork(0, 128),
+ },
+ },
+ },
+ },
+ "wildcard_address": {
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "name": {
+ Type: schema.TypeString,
+ Required: true,
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatAddressName),
+ },
+ "description": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "value": {
+ Type: schema.TypeString,
+ Required: true,
+ ValidateDiagFunc: validateWildcardFunc(),
+ },
+ },
+ },
+ },
+ "dns_name": {
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "name": {
+ Type: schema.TypeString,
+ Required: true,
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatAddressName),
+ },
+ "description": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "value": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ },
+ },
+ },
+ "range_address": {
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "name": {
+ Type: schema.TypeString,
+ Required: true,
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatAddressName),
+ },
+ "description": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "from": {
+ Type: schema.TypeString,
+ Required: true,
+ ValidateFunc: validation.IsIPAddress,
+ },
+ "to": {
+ Type: schema.TypeString,
+ Required: true,
+ ValidateFunc: validation.IsIPAddress,
+ },
+ },
+ },
+ },
+ "address_set": {
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "name": {
+ Type: schema.TypeString,
+ Required: true,
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatAddressName),
+ },
+ "address": {
+ Type: schema.TypeList,
+ Required: true,
+ MinItems: 1,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ "description": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
+func resourceSecurityAddressBookCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setAddressBook(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ defer sess.closeSession(jnprSess)
+ if !checkCompatibilitySecurity(jnprSess) {
+ return diag.FromErr(fmt.Errorf("security policy not compatible with Junos device %s",
+ jnprSess.SystemInformation.HardwareModel))
+ }
+ sess.configLock(jnprSess)
+ addressBookExists, err := checkAddressBookExists(d.Get("name").(string), m, jnprSess)
+ if err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ if addressBookExists {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(fmt.Errorf("security address book %v already exists", d.Get("name").(string)))
+ }
+ if err := setAddressBook(d, m, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ var diagWarns diag.Diagnostics
+ warns, err := sess.commitConf("create resource junos_security_address_book", jnprSess)
+ appendDiagWarns(&diagWarns, warns)
+ if err != nil {
+ sess.configClear(jnprSess)
+
+ return append(diagWarns, diag.FromErr(err)...)
+ }
+ addressBookExists, err = checkAddressBookExists(d.Get("name").(string), m, jnprSess)
+ if err != nil {
+ return append(diagWarns, diag.FromErr(err)...)
+ }
+ if addressBookExists {
+ d.SetId(d.Get("name").(string))
+ } else {
+ return append(diagWarns, diag.FromErr(fmt.Errorf("security address book %v does not exists after commit "+
+ "=> check your config", d.Get("name").(string)))...)
+ }
+
+ return append(diagWarns, resourceSecurityAddressBookReadWJnprSess(d, m, jnprSess)...)
+}
+
+func resourceSecurityAddressBookRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ sess := m.(*Session)
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ defer sess.closeSession(jnprSess)
+
+ return resourceSecurityAddressBookReadWJnprSess(d, m, jnprSess)
+}
+func resourceSecurityAddressBookReadWJnprSess(d *schema.ResourceData, m interface{},
+ jnprSess *NetconfObject) diag.Diagnostics {
+ mutex.Lock()
+ addressOptions, err := readSecurityAddressBook(d.Get("name").(string), m, jnprSess)
+ mutex.Unlock()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ if addressOptions.name == "" {
+ d.SetId("")
+ } else {
+ fillAddressBookData(d, addressOptions)
+ }
+
+ return nil
+}
+
+func resourceSecurityAddressBookUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ d.Partial(true)
+ sess := m.(*Session)
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ defer sess.closeSession(jnprSess)
+ sess.configLock(jnprSess)
+
+ if err := delSecurityAddressBook(d.Get("name").(string), m, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+
+ if err := setAddressBook(d, m, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ var diagWarns diag.Diagnostics
+ warns, err := sess.commitConf("update resource junos_security_address_book", jnprSess)
+ appendDiagWarns(&diagWarns, warns)
+ if err != nil {
+ sess.configClear(jnprSess)
+
+ return append(diagWarns, diag.FromErr(err)...)
+ }
+ d.Partial(false)
+
+ return append(diagWarns, resourceSecurityAddressBookReadWJnprSess(d, m, jnprSess)...)
+}
+
+func resourceSecurityAddressBookDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ sess := m.(*Session)
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ defer sess.closeSession(jnprSess)
+ sess.configLock(jnprSess)
+ if err := delSecurityAddressBook(d.Get("name").(string), m, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ var diagWarns diag.Diagnostics
+ warns, err := sess.commitConf("delete resource junos_security_address_book", jnprSess)
+ appendDiagWarns(&diagWarns, warns)
+ if err != nil {
+ sess.configClear(jnprSess)
+
+ return append(diagWarns, diag.FromErr(err)...)
+ }
+
+ return diagWarns
+}
+
+func resourceSecurityAddressBookImport(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) {
+ sess := m.(*Session)
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return nil, err
+ }
+ defer sess.closeSession(jnprSess)
+ result := make([]*schema.ResourceData, 1)
+ securityAddressBookExists, err := checkAddressBookExists(d.Id(), m, jnprSess)
+ if err != nil {
+ return nil, err
+ }
+ if !securityAddressBookExists {
+ return nil, fmt.Errorf("don't find address book with id '%v' (id must be )", d.Id())
+ }
+ addressOptions, err := readSecurityAddressBook(d.Id(), m, jnprSess)
+ if err != nil {
+ return nil, err
+ }
+ fillAddressBookData(d, addressOptions)
+
+ result[0] = d
+
+ return result, nil
+}
+
+func checkAddressBookExists(addrBook string, m interface{}, jnprSess *NetconfObject) (bool, error) {
+ sess := m.(*Session)
+
+ addrBookConfig, err := sess.command("show configuration security address-book "+addrBook+
+ " | display set", jnprSess)
+ if err != nil {
+ return false, err
+ }
+ if addrBookConfig == emptyWord {
+ return false, nil
+ }
+
+ return true, nil
+}
+
+func setAddressBook(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
+ sess := m.(*Session)
+ configSet := make([]string, 0)
+ setPrefix := "set security address-book " + d.Get("name").(string)
+
+ if d.Get("description").(string) != "" {
+ configSet = append(configSet, setPrefix+" description \""+d.Get("description").(string)+"\"")
+ }
+ for _, v := range d.Get("attach_zone").([]interface{}) {
+ if d.Get("name").(string) == "global" {
+ return fmt.Errorf("cannot attach global address book to a zone")
+ }
+ attachZone := v.(string)
+ configSet = append(configSet, setPrefix+" attach zone "+attachZone)
+ }
+ for _, v := range d.Get("network_address").([]interface{}) {
+ address := v.(map[string]interface{})
+ setPrefixAddr := setPrefix + " address " + address["name"].(string) + " "
+ if address["description"].(string) != "" {
+ configSet = append(configSet, setPrefixAddr+"description \""+address["description"].(string)+"\"")
+ }
+ configSet = append(configSet, setPrefixAddr+address["value"].(string))
+ }
+ for _, v := range d.Get("wildcard_address").([]interface{}) {
+ address := v.(map[string]interface{})
+ setPrefixAddr := setPrefix + " address " + address["name"].(string)
+ if address["description"].(string) != "" {
+ configSet = append(configSet, setPrefixAddr+"description \""+address["description"].(string)+"\"")
+ }
+ configSet = append(configSet, setPrefixAddr+" wildcard-address "+address["value"].(string))
+ }
+ for _, v := range d.Get("dns_name").([]interface{}) {
+ address := v.(map[string]interface{})
+ setPrefixAddr := setPrefix + " address " + address["name"].(string)
+ if address["description"].(string) != "" {
+ configSet = append(configSet, setPrefixAddr+"description \""+address["description"].(string)+"\"")
+ }
+ configSet = append(configSet, setPrefixAddr+" dns-name "+address["value"].(string))
+ }
+ for _, v := range d.Get("range_address").([]interface{}) {
+ address := v.(map[string]interface{})
+ setPrefixAddr := setPrefix + " address " + address["name"].(string)
+ if address["description"].(string) != "" {
+ configSet = append(configSet, setPrefixAddr+"description \""+address["description"].(string)+"\"")
+ }
+ configSet = append(configSet, setPrefixAddr+" range-address "+address["from"].(string)+" to "+address["to"].(string))
+ }
+ for _, v := range d.Get("address_set").([]interface{}) {
+ addressSet := v.(map[string]interface{})
+ setPrefixAddrSet := setPrefix + " address-set " + addressSet["name"].(string)
+ if addressSet["description"].(string) != "" {
+ configSet = append(configSet, setPrefixAddrSet+"description \""+addressSet["description"].(string)+"\"")
+ }
+ for _, addr := range addressSet["address"].([]interface{}) {
+ configSet = append(configSet, setPrefixAddrSet+" address "+addr.(string))
+ }
+ }
+
+ return sess.configSet(configSet, jnprSess)
+}
+
+func readSecurityAddressBook(addrBook string, m interface{}, jnprSess *NetconfObject) (addressBookOptions, error) {
+ sess := m.(*Session)
+ var confRead addressBookOptions
+
+ securityAddressBookConfig, err := sess.command("show configuration security address-book "+addrBook+
+ " | display set relative", jnprSess)
+ if err != nil {
+ return confRead, err
+ }
+ descMap := make(map[string]string)
+ if securityAddressBookConfig != emptyWord {
+ confRead.name = addrBook
+ for _, item := range strings.Split(securityAddressBookConfig, "\n") {
+ if strings.Contains(item, "") {
+ continue
+ }
+ if strings.Contains(item, "") {
+ break
+ }
+ itemTrim := strings.TrimPrefix(item, setLineStart)
+ switch {
+ case strings.HasPrefix(itemTrim, "description "):
+ confRead.description = strings.Trim(strings.TrimPrefix(itemTrim, "description "), "\"")
+ case strings.HasPrefix(itemTrim, "address "):
+ addressSplit := strings.Split(itemTrim, " ")
+ itemTrimAddress := strings.TrimPrefix(itemTrim, "address "+addressSplit[1]+" ")
+ switch {
+ case strings.HasPrefix(itemTrimAddress, "description "):
+ descMap[addressSplit[1]] = strings.Trim(strings.TrimPrefix(itemTrimAddress, "description "), "\"")
+ case strings.HasPrefix(itemTrimAddress, "wildcard-address "):
+ confRead.wildcardAddress = append(confRead.wildcardAddress, map[string]interface{}{
+ "name": addressSplit[1],
+ "description": descMap[addressSplit[1]],
+ "value": strings.TrimPrefix(itemTrimAddress, "wildcard-address "),
+ })
+ case strings.HasPrefix(itemTrimAddress, "range-address "):
+ rangeAddr := strings.TrimPrefix(itemTrimAddress, "range-address ")
+ addresses := strings.Split(rangeAddr, " ")
+ confRead.rangeAddress = append(confRead.rangeAddress, map[string]interface{}{
+ "name": addressSplit[1],
+ "description": descMap[addressSplit[1]],
+ "from": addresses[0],
+ "to": addresses[2],
+ })
+ case strings.HasPrefix(itemTrimAddress, "dns-name "):
+ confRead.dnsName = append(confRead.dnsName, map[string]interface{}{
+ "name": addressSplit[1],
+ "description": descMap[addressSplit[1]],
+ "value": strings.TrimPrefix(itemTrimAddress, "dns-name "),
+ })
+ default:
+ confRead.networkAddress = append(confRead.networkAddress, map[string]interface{}{
+ "name": addressSplit[1],
+ "description": descMap[addressSplit[1]],
+ "value": itemTrimAddress,
+ })
+ }
+ case strings.HasPrefix(itemTrim, "address-set "):
+ addressSetSplit := strings.Split(strings.TrimPrefix(itemTrim, "address-set "), " ")
+ m := map[string]interface{}{
+ "name": addressSetSplit[0],
+ "address": make([]string, 0),
+ "description": "",
+ }
+ m, confRead.addressSet = copyAndRemoveItemMapList("name", false, m, confRead.addressSet)
+ if addressSetSplit[1] == "description" {
+ m["description"] = strings.Trim(strings.TrimPrefix(
+ itemTrim, "address-set "+addressSetSplit[0]+" description "), "\"")
+ } else {
+ m["address"] = append(m["address"].([]string), addressSetSplit[2])
+ }
+ confRead.addressSet = append(confRead.addressSet, m)
+ case strings.HasPrefix(itemTrim, "attach zone"):
+ confRead.attachZone = append(confRead.attachZone, strings.TrimPrefix(itemTrim, "attach zone "))
+ }
+ }
+ }
+ confRead.networkAddress = copyAddressDescriptions(descMap, confRead.networkAddress)
+ confRead.dnsName = copyAddressDescriptions(descMap, confRead.dnsName)
+ confRead.rangeAddress = copyAddressDescriptions(descMap, confRead.rangeAddress)
+ confRead.wildcardAddress = copyAddressDescriptions(descMap, confRead.wildcardAddress)
+
+ return confRead, nil
+}
+
+func delSecurityAddressBook(addrBook string, m interface{}, jnprSess *NetconfObject) error {
+ sess := m.(*Session)
+ configSet := make([]string, 0, 1)
+ configSet = append(configSet, "delete security address-book "+addrBook)
+
+ return sess.configSet(configSet, jnprSess)
+}
+
+func fillAddressBookData(d *schema.ResourceData, addressOptions addressBookOptions) {
+ if tfErr := d.Set("name", addressOptions.name); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("description", addressOptions.description); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("attach_zone", addressOptions.attachZone); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("network_address", addressOptions.networkAddress); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("wildcard_address", addressOptions.wildcardAddress); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("dns_name", addressOptions.dnsName); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("range_address", addressOptions.rangeAddress); tfErr != nil {
+ panic(tfErr)
+ }
+ if tfErr := d.Set("address_set", addressOptions.addressSet); tfErr != nil {
+ panic(tfErr)
+ }
+}
+
+func copyAddressDescriptions(descMap map[string]string,
+ addrList []map[string]interface{}) (newList []map[string]interface{}) {
+ for _, ele := range addrList {
+ ele["description"] = descMap[ele["name"].(string)]
+ newList = append(newList, ele)
+ }
+
+ return newList
+}
diff --git a/junos/resource_security_address_book_test.go b/junos/resource_security_address_book_test.go
new file mode 100644
index 00000000..c592ecbc
--- /dev/null
+++ b/junos/resource_security_address_book_test.go
@@ -0,0 +1,177 @@
+package junos_test
+
+import (
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+)
+
+func TestAccJunosSecurityAddressBook_basic(t *testing.T) {
+ if os.Getenv("TESTACC_SWITCH") == "" {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ Providers: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccJunosSecurityAddressBookConfigCreate(),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "name", "global"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "description", "testacc global description"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "network_address.#", "2"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "network_address.0.name", "testacc_network"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "network_address.0.description", "testacc_network description"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "network_address.0.value", "10.0.0.0/24"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "network_address.1.name", "testacc_network2"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "network_address.1.description", "testacc_network description2"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "network_address.1.value", "10.1.0.0/24"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "wildcard_address.#", "1"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "wildcard_address.0.value", "10.0.0.0/255.255.0.255"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "wildcard_address.0.name", "testacc_wildcard"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "range_address.#", "1"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "range_address.0.name", "testacc_range"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "range_address.0.from", "10.1.1.1"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "range_address.0.to", "10.1.1.5"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "dns_name.#", "1"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "dns_name.0.name", "testacc_dns"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "dns_name.0.value", "google.com"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "address_set.#", "1"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "address_set.0.address.#", "3"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityNamedAddressBook",
+ "name", "testacc_secAddrBook"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityNamedAddressBook",
+ "attach_zone.#", "2"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityNamedAddressBook",
+ "attach_zone.0", "testacc_secZoneAddr1"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityNamedAddressBook",
+ "attach_zone.1", "testacc_secZoneAddr2"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityNamedAddressBook",
+ "network_address.#", "1"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityNamedAddressBook",
+ "network_address.0.name", "testacc_network"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityNamedAddressBook",
+ "network_address.0.value", "10.1.2.3/32"),
+ ),
+ },
+ {
+ Config: testAccJunosSecurityAddressBookConfigUpdate(),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "network_address.#", "1"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityGlobalAddressBook",
+ "network_address.0.value", "10.1.0.0/24"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityNamedAddressBook",
+ "network_address.#", "1"),
+ resource.TestCheckResourceAttr("junos_security_address_book.testacc_securityNamedAddressBook",
+ "network_address.0.value", "10.1.2.4/32"),
+ ),
+ },
+ {
+ ResourceName: "junos_security_address_book.testacc_securityGlobalAddressBook",
+ ImportState: true,
+ ImportStateVerify: true,
+ },
+ },
+ })
+ }
+}
+
+func testAccJunosSecurityAddressBookConfigCreate() string {
+ return `
+resource "junos_security_zone" "testacc_secZoneAddr1" {
+ name = "testacc_secZoneAddr1"
+}
+resource "junos_security_zone" "testacc_secZoneAddr2" {
+ name = "testacc_secZoneAddr2"
+}
+
+resource "junos_security_address_book" "testacc_securityGlobalAddressBook" {
+ description = "testacc global description"
+ network_address {
+ name = "testacc_network"
+ description = "testacc_network description"
+ value = "10.0.0.0/24"
+ }
+ wildcard_address {
+ name = "testacc_wildcard"
+ value = "10.0.0.0/255.255.0.255"
+ }
+ network_address {
+ name = "testacc_network2"
+ description = "testacc_network description2"
+ value = "10.1.0.0/24"
+ }
+ range_address {
+ name = "testacc_range"
+ from = "10.1.1.1"
+ to = "10.1.1.5"
+ }
+ dns_name {
+ name = "testacc_dns"
+ value = "google.com"
+ }
+ address_set {
+ name = "testacc_addressSet"
+ address = ["testacc_network", "testacc_wildcard", "testacc_network2"]
+ }
+}
+
+resource "junos_security_address_book" "testacc_securityNamedAddressBook" {
+ name = "testacc_secAddrBook"
+ attach_zone = [junos_security_zone.testacc_secZoneAddr1.name, junos_security_zone.testacc_secZoneAddr2.name]
+ network_address {
+ name = "testacc_network"
+ value = "10.1.2.3/32"
+ }
+}
+`
+}
+
+func testAccJunosSecurityAddressBookConfigUpdate() string {
+ return `
+resource "junos_security_zone" "testacc_secZoneAddr1" {
+ name = "testacc_secZoneAddr1"
+}
+resource "junos_security_zone" "testacc_secZoneAddr2" {
+ name = "testacc_secZoneAddr2"
+}
+
+resource junos_security_address_book "testacc_securityGlobalAddressBook" {
+ description = "testacc global description"
+ network_address {
+ name = "testacc_network"
+ description = "testacc_network description"
+ value = "10.1.0.0/24"
+ }
+}
+
+resource junos_security_address_book "testacc_securityNamedAddressBook" {
+ name = "testacc_secAddrBook"
+ network_address {
+ name = "testacc_network"
+ value = "10.1.2.4/32"
+ }
+}
+`
+}
diff --git a/junos/resource_security_global_policy.go b/junos/resource_security_global_policy.go
new file mode 100644
index 00000000..b1c48fa6
--- /dev/null
+++ b/junos/resource_security_global_policy.go
@@ -0,0 +1,617 @@
+package junos
+
+import (
+ "context"
+ "fmt"
+ "strings"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
+)
+
+type globalPolicyOptions struct {
+ policy []map[string]interface{}
+}
+
+func resourceSecurityGlobalPolicy() *schema.Resource {
+ return &schema.Resource{
+ CreateContext: resourceSecurityGlobalPolicyCreate,
+ ReadContext: resourceSecurityGlobalPolicyRead,
+ UpdateContext: resourceSecurityGlobalPolicyUpdate,
+ DeleteContext: resourceSecurityGlobalPolicyDelete,
+ Importer: &schema.ResourceImporter{
+ State: resourceSecurityGlobalPolicyImport,
+ },
+ Schema: map[string]*schema.Schema{
+ "policy": {
+ Type: schema.TypeList,
+ Required: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "name": {
+ Type: schema.TypeString,
+ Required: true,
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
+ },
+ "match_source_address": {
+ Type: schema.TypeList,
+ Required: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ "match_destination_address": {
+ Type: schema.TypeList,
+ Required: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ "match_application": {
+ Type: schema.TypeList,
+ Required: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ "match_from_zone": {
+ Type: schema.TypeList,
+ Required: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ "match_to_zone": {
+ Type: schema.TypeList,
+ Required: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ "then": {
+ Type: schema.TypeString,
+ Optional: true,
+ Default: permitWord,
+ ValidateFunc: validation.StringInSlice([]string{permitWord, "reject", "deny"}, false),
+ },
+ "count": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ "log_init": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ "log_close": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ "permit_application_services": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "application_firewall_rule_set": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "application_traffic_control_rule_set": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "gprs_gtp_profile": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "gprs_sctp_profile": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "idp": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ "redirect_wx": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ "reverse_redirect_wx": {
+ Type: schema.TypeBool,
+ Optional: true,
+ },
+ "security_intelligence_policy": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "ssl_proxy": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "profile_name": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ },
+ },
+ },
+ "uac_policy": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "captive_portal": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ },
+ },
+ },
+ "utm_policy": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
+func resourceSecurityGlobalPolicyCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSecurityGlobalPolicy(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId("security_global_policy")
+
+ return nil
+ }
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ defer sess.closeSession(jnprSess)
+ if !checkCompatibilitySecurity(jnprSess) {
+ return diag.FromErr(fmt.Errorf("security policies global not compatible with Junos device %s",
+ jnprSess.SystemInformation.HardwareModel))
+ }
+ sess.configLock(jnprSess)
+ glbPolicy, err := readSecurityGlobalPolicy(m, jnprSess)
+ if err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ if len(glbPolicy.policy) != 0 {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(fmt.Errorf("security policies global already set"))
+ }
+
+ if err := setSecurityGlobalPolicy(d, m, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ var diagWarns diag.Diagnostics
+ warns, err := sess.commitConf("create resource junos_security_global_policy", jnprSess)
+ appendDiagWarns(&diagWarns, warns)
+ if err != nil {
+ sess.configClear(jnprSess)
+
+ return append(diagWarns, diag.FromErr(err)...)
+ }
+ d.SetId("security_global_policy")
+
+ return append(diagWarns, resourceSecurityGlobalPolicyReadWJnprSess(d, m, jnprSess)...)
+}
+func resourceSecurityGlobalPolicyRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ sess := m.(*Session)
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ defer sess.closeSession(jnprSess)
+
+ return resourceSecurityGlobalPolicyReadWJnprSess(d, m, jnprSess)
+}
+func resourceSecurityGlobalPolicyReadWJnprSess(
+ d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) diag.Diagnostics {
+ mutex.Lock()
+ globalPolicyOptions, err := readSecurityGlobalPolicy(m, jnprSess)
+ mutex.Unlock()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ fillSecurityGlobalPolicyData(d, globalPolicyOptions)
+
+ return nil
+}
+func resourceSecurityGlobalPolicyUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ d.Partial(true)
+ sess := m.(*Session)
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ defer sess.closeSession(jnprSess)
+ sess.configLock(jnprSess)
+
+ if err := delSecurityGlobalPolicy(m, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+
+ if err := setSecurityGlobalPolicy(d, m, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ var diagWarns diag.Diagnostics
+ warns, err := sess.commitConf("update resource junos_security_global_policy", jnprSess)
+ appendDiagWarns(&diagWarns, warns)
+ if err != nil {
+ sess.configClear(jnprSess)
+
+ return append(diagWarns, diag.FromErr(err)...)
+ }
+ d.Partial(false)
+
+ return append(diagWarns, resourceSecurityGlobalPolicyReadWJnprSess(d, m, jnprSess)...)
+}
+func resourceSecurityGlobalPolicyDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ sess := m.(*Session)
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ defer sess.closeSession(jnprSess)
+ sess.configLock(jnprSess)
+ if err := delSecurityGlobalPolicy(m, jnprSess); err != nil {
+ sess.configClear(jnprSess)
+
+ return diag.FromErr(err)
+ }
+ var diagWarns diag.Diagnostics
+ warns, err := sess.commitConf("delete resource junos_security_global_policy", jnprSess)
+ appendDiagWarns(&diagWarns, warns)
+ if err != nil {
+ sess.configClear(jnprSess)
+
+ return append(diagWarns, diag.FromErr(err)...)
+ }
+
+ return diagWarns
+}
+func resourceSecurityGlobalPolicyImport(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) {
+ sess := m.(*Session)
+ jnprSess, err := sess.startNewSession()
+ if err != nil {
+ return nil, err
+ }
+ defer sess.closeSession(jnprSess)
+ result := make([]*schema.ResourceData, 1)
+ globalPolicyOptions, err := readSecurityGlobalPolicy(m, jnprSess)
+ if err != nil {
+ return nil, err
+ }
+ fillSecurityGlobalPolicyData(d, globalPolicyOptions)
+ result[0] = d
+
+ return result, nil
+}
+
+func setSecurityGlobalPolicy(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
+ sess := m.(*Session)
+ configSet := make([]string, 0)
+
+ setPrefix := "set security policies global policy "
+ for _, v := range d.Get("policy").([]interface{}) {
+ policy := v.(map[string]interface{})
+ setPrefixPolicy := setPrefix + policy["name"].(string)
+ if len(policy["match_source_address"].([]interface{})) != 0 {
+ for _, address := range policy["match_source_address"].([]interface{}) {
+ configSet = append(configSet, setPrefixPolicy+" match source-address "+address.(string))
+ }
+ } else {
+ configSet = append(configSet, setPrefixPolicy+" match source-address any")
+ }
+ if len(policy["match_destination_address"].([]interface{})) != 0 {
+ for _, address := range policy["match_destination_address"].([]interface{}) {
+ configSet = append(configSet, setPrefixPolicy+" match destination-address "+address.(string))
+ }
+ } else {
+ configSet = append(configSet, setPrefixPolicy+" match destination-address any")
+ }
+ if len(policy["match_application"].([]interface{})) != 0 {
+ for _, app := range policy["match_application"].([]interface{}) {
+ configSet = append(configSet, setPrefixPolicy+" match application "+app.(string))
+ }
+ } else {
+ configSet = append(configSet, setPrefixPolicy+" match application any")
+ }
+ for _, v := range policy["match_from_zone"].([]interface{}) {
+ configSet = append(configSet, setPrefixPolicy+" match from-zone "+v.(string))
+ }
+ for _, v := range policy["match_to_zone"].([]interface{}) {
+ configSet = append(configSet, setPrefixPolicy+" match to-zone "+v.(string))
+ }
+ configSet = append(configSet, setPrefixPolicy+" then "+policy["then"].(string))
+ if policy["count"].(bool) {
+ configSet = append(configSet, setPrefixPolicy+" then count")
+ }
+ if policy["log_init"].(bool) {
+ configSet = append(configSet, setPrefixPolicy+" then log session-init")
+ }
+ if policy["log_close"].(bool) {
+ configSet = append(configSet, setPrefixPolicy+" then log session-close")
+ }
+ if len(policy["permit_application_services"].([]interface{})) > 0 {
+ if policy["permit_application_services"].([]interface{})[0] == nil {
+ return fmt.Errorf("permit_application_services block is empty")
+ }
+ if policy["then"].(string) != permitWord {
+ return fmt.Errorf("conflict policy then %v and policy permit_application_services",
+ policy["then"].(string))
+ }
+ configSetAppSvc, err := setGlobalPolicyPermitApplicationServices(setPrefixPolicy,
+ policy["permit_application_services"].([]interface{})[0].(map[string]interface{}))
+ if err != nil {
+ return err
+ }
+ configSet = append(configSet, configSetAppSvc...)
+ }
+ }
+
+ return sess.configSet(configSet, jnprSess)
+}
+func readSecurityGlobalPolicy(m interface{}, jnprSess *NetconfObject) (globalPolicyOptions, error) {
+ sess := m.(*Session)
+ var confRead globalPolicyOptions
+
+ policyConfig, err := sess.command("show configuration security policies global | display set relative ", jnprSess)
+ if err != nil {
+ return confRead, err
+ }
+ policyList := make([]map[string]interface{}, 0)
+ if policyConfig != emptyWord {
+ for _, item := range strings.Split(policyConfig, "\n") {
+ if strings.Contains(item, "") {
+ continue
+ }
+ if strings.Contains(item, "") {
+ break
+ }
+ itemTrim := strings.TrimPrefix(item, setLineStart)
+ if strings.HasPrefix(itemTrim, "policy ") {
+ policyLineCut := strings.Split(itemTrim, " ")
+ m := genMapGlobalPolicyWithName(policyLineCut[1])
+ m, policyList = copyAndRemoveItemMapList("name", false, m, policyList)
+ itemTrimPolicy := strings.TrimPrefix(itemTrim, "policy "+policyLineCut[1]+" ")
+ switch {
+ case strings.HasPrefix(itemTrimPolicy, "match source-address "):
+ m["match_source_address"] = append(m["match_source_address"].([]string),
+ strings.TrimPrefix(itemTrimPolicy, "match source-address "))
+ case strings.HasPrefix(itemTrimPolicy, "match destination-address "):
+ m["match_destination_address"] = append(m["match_destination_address"].([]string),
+ strings.TrimPrefix(itemTrimPolicy, "match destination-address "))
+ case strings.HasPrefix(itemTrimPolicy, "match application "):
+ m["match_application"] = append(m["match_application"].([]string),
+ strings.TrimPrefix(itemTrimPolicy, "match application "))
+ case strings.HasPrefix(itemTrimPolicy, "match from-zone "):
+ m["match_from_zone"] = append(m["match_from_zone"].([]string),
+ strings.TrimPrefix(itemTrimPolicy, "match from-zone "))
+ case strings.HasPrefix(itemTrimPolicy, "match to-zone "):
+ m["match_to_zone"] = append(m["match_to_zone"].([]string),
+ strings.TrimPrefix(itemTrimPolicy, "match to-zone "))
+ case strings.HasPrefix(itemTrimPolicy, "then "):
+ switch {
+ case strings.HasSuffix(itemTrimPolicy, permitWord),
+ strings.HasSuffix(itemTrimPolicy, "deny"),
+ strings.HasSuffix(itemTrimPolicy, "reject"):
+ m["then"] = strings.TrimPrefix(itemTrimPolicy, "then ")
+ case itemTrimPolicy == "then count":
+ m["count"] = true
+ case itemTrimPolicy == "then log session-init":
+ m["log_init"] = true
+ case itemTrimPolicy == "then log session-close":
+ m["log_close"] = true
+ case strings.HasPrefix(itemTrimPolicy, "then permit application-services"):
+ m["then"] = permitWord
+ m["permit_application_services"] = readGlobalPolicyPermitApplicationServices(itemTrimPolicy,
+ m["permit_application_services"])
+ }
+ }
+ policyList = append(policyList, m)
+ }
+ }
+ }
+ confRead.policy = policyList
+
+ return confRead, nil
+}
+func delSecurityGlobalPolicy(m interface{}, jnprSess *NetconfObject) error {
+ sess := m.(*Session)
+ configSet := make([]string, 0, 1)
+ configSet = append(configSet, "delete security policies global")
+
+ return sess.configSet(configSet, jnprSess)
+}
+
+func fillSecurityGlobalPolicyData(d *schema.ResourceData, globalPolicyOptions globalPolicyOptions) {
+ if tfErr := d.Set("policy", globalPolicyOptions.policy); tfErr != nil {
+ panic(tfErr)
+ }
+}
+
+func genMapGlobalPolicyWithName(name string) map[string]interface{} {
+ return map[string]interface{}{
+ "name": name,
+ "match_source_address": make([]string, 0),
+ "match_destination_address": make([]string, 0),
+ "match_application": make([]string, 0),
+ "match_from_zone": make([]string, 0),
+ "match_to_zone": make([]string, 0),
+ "then": "",
+ "count": false,
+ "log_init": false,
+ "log_close": false,
+ "permit_application_services": make([]map[string]interface{}, 0),
+ }
+}
+
+func readGlobalPolicyPermitApplicationServices(itemTrimPolicy string,
+ permitApplicationServices interface{}) []map[string]interface{} {
+ applicationServices := map[string]interface{}{
+ "application_firewall_rule_set": "",
+ "application_traffic_control_rule_set": "",
+ "gprs_gtp_profile": "",
+ "gprs_sctp_profile": "",
+ "idp": false,
+ "redirect_wx": false,
+ "reverse_redirect_wx": false,
+ "security_intelligence_policy": "",
+ "ssl_proxy": make([]map[string]interface{}, 0, 1),
+ "uac_policy": make([]map[string]interface{}, 0, 1),
+ "utm_policy": "",
+ }
+ if len(permitApplicationServices.([]map[string]interface{})) > 0 {
+ for k, v := range permitApplicationServices.([]map[string]interface{})[0] {
+ applicationServices[k] = v
+ }
+ }
+ itemTrimPolicyPermitAppSvc := strings.TrimPrefix(itemTrimPolicy, "then permit application-services ")
+ switch {
+ case strings.HasPrefix(itemTrimPolicyPermitAppSvc, "application-firewall rule-set "):
+ applicationServices["application_firewall_rule_set"] = strings.Trim(strings.TrimPrefix(itemTrimPolicyPermitAppSvc,
+ "application-firewall rule-set "), "\"")
+ case strings.HasPrefix(itemTrimPolicyPermitAppSvc, "application-traffic-control rule-set "):
+ applicationServices["application_traffic_control_rule_set"] = strings.Trim(
+ strings.TrimPrefix(itemTrimPolicyPermitAppSvc, "application-traffic-control rule-set "), "\"")
+ case strings.HasPrefix(itemTrimPolicyPermitAppSvc, "gprs-gtp-profile "):
+ applicationServices["gprs_gtp_profile"] = strings.Trim(strings.TrimPrefix(itemTrimPolicyPermitAppSvc,
+ "gprs-gtp-profile "), "\"")
+ case strings.HasPrefix(itemTrimPolicyPermitAppSvc, "gprs-sctp-profile "):
+ applicationServices["gprs_sctp_profile"] = strings.Trim(strings.TrimPrefix(itemTrimPolicyPermitAppSvc,
+ "gprs-sctp-profile "), "\"")
+ case itemTrimPolicyPermitAppSvc == "idp":
+ applicationServices["idp"] = true
+ case itemTrimPolicyPermitAppSvc == "redirect-wx":
+ applicationServices["redirect_wx"] = true
+ case itemTrimPolicyPermitAppSvc == "reverse-redirect-wx":
+ applicationServices["reverse_redirect_wx"] = true
+ case strings.HasPrefix(itemTrimPolicyPermitAppSvc, "security-intelligence-policy "):
+ applicationServices["security_intelligence_policy"] = strings.Trim(strings.TrimPrefix(itemTrimPolicyPermitAppSvc,
+ "security-intelligence-policy "), "\"")
+ case strings.HasPrefix(itemTrimPolicyPermitAppSvc, "ssl-proxy"):
+ if strings.HasPrefix(itemTrimPolicyPermitAppSvc, "ssl-proxy profile-name ") {
+ applicationServices["ssl_proxy"] = append(applicationServices["ssl_proxy"].([]map[string]interface{}),
+ map[string]interface{}{
+ "profile_name": strings.Trim(strings.TrimPrefix(itemTrimPolicyPermitAppSvc, "ssl-proxy profile-name "), "\""),
+ })
+ } else {
+ applicationServices["ssl_proxy"] = append(applicationServices["ssl_proxy"].([]map[string]interface{}),
+ map[string]interface{}{
+ "profile_name": "",
+ })
+ }
+ case strings.HasPrefix(itemTrimPolicyPermitAppSvc, "uac-policy"):
+ if strings.HasPrefix(itemTrimPolicyPermitAppSvc, "uac-policy captive-portal ") {
+ applicationServices["uac_policy"] = append(applicationServices["uac_policy"].([]map[string]interface{}),
+ map[string]interface{}{
+ "captive_portal": strings.Trim(strings.TrimPrefix(itemTrimPolicyPermitAppSvc, "uac-policy captive-portal "), "\""),
+ })
+ } else {
+ applicationServices["uac_policy"] = append(applicationServices["uac_policy"].([]map[string]interface{}),
+ map[string]interface{}{
+ "captive_portal": "",
+ })
+ }
+ case strings.HasPrefix(itemTrimPolicyPermitAppSvc, "utm-policy "):
+ applicationServices["utm_policy"] = strings.Trim(strings.TrimPrefix(itemTrimPolicyPermitAppSvc, "utm-policy "), "\"")
+ }
+
+ // override (maxItem = 1)
+ return []map[string]interface{}{applicationServices}
+}
+
+func setGlobalPolicyPermitApplicationServices(setPrefixPolicy string,
+ policyPermitApplicationServices map[string]interface{}) ([]string, error) {
+ configSet := make([]string, 0)
+ setPrefixPolicyPermitAppSvc := setPrefixPolicy + " then permit application-services "
+ if policyPermitApplicationServices["application_firewall_rule_set"].(string) != "" {
+ configSet = append(configSet, setPrefixPolicyPermitAppSvc+
+ "application-firewall rule-set \""+
+ policyPermitApplicationServices["application_firewall_rule_set"].(string)+"\"")
+ }
+ if policyPermitApplicationServices["application_traffic_control_rule_set"].(string) != "" {
+ configSet = append(configSet, setPrefixPolicyPermitAppSvc+
+ "application-traffic-control rule-set \""+
+ policyPermitApplicationServices["application_traffic_control_rule_set"].(string)+"\"")
+ }
+ if policyPermitApplicationServices["gprs_gtp_profile"].(string) != "" {
+ configSet = append(configSet, setPrefixPolicyPermitAppSvc+
+ "gprs-gtp-profile \""+policyPermitApplicationServices["gprs_gtp_profile"].(string)+"\"")
+ }
+ if policyPermitApplicationServices["gprs_sctp_profile"].(string) != "" {
+ configSet = append(configSet, setPrefixPolicyPermitAppSvc+
+ "gprs-sctp-profile \""+policyPermitApplicationServices["gprs_sctp_profile"].(string)+"\"")
+ }
+ if policyPermitApplicationServices["idp"].(bool) {
+ configSet = append(configSet, setPrefixPolicyPermitAppSvc+
+ "idp")
+ }
+ if policyPermitApplicationServices["redirect_wx"].(bool) &&
+ policyPermitApplicationServices["reverse_redirect_wx"].(bool) {
+ return configSet, fmt.Errorf("conflict redirect_wx and reverse_redirect_wx enabled both")
+ }
+ if policyPermitApplicationServices["redirect_wx"].(bool) {
+ configSet = append(configSet, setPrefixPolicyPermitAppSvc+
+ "redirect-wx")
+ }
+ if policyPermitApplicationServices["reverse_redirect_wx"].(bool) {
+ configSet = append(configSet, setPrefixPolicyPermitAppSvc+
+ "reverse-redirect-wx")
+ }
+ if policyPermitApplicationServices["security_intelligence_policy"].(string) != "" {
+ configSet = append(configSet, setPrefixPolicyPermitAppSvc+
+ "security-intelligence-policy \""+
+ policyPermitApplicationServices["security_intelligence_policy"].(string)+"\"")
+ }
+ if len(policyPermitApplicationServices["ssl_proxy"].([]interface{})) > 0 {
+ if policyPermitApplicationServices["ssl_proxy"].([]interface{})[0] != nil {
+ policyPermitApplicationServicesSSLProxy :=
+ policyPermitApplicationServices["ssl_proxy"].([]interface{})[0].(map[string]interface{})
+ if policyPermitApplicationServicesSSLProxy["profile_name"].(string) != "" {
+ configSet = append(configSet, setPrefixPolicyPermitAppSvc+
+ "ssl-proxy profile-name \""+
+ policyPermitApplicationServicesSSLProxy["profile_name"].(string)+"\"")
+ } else {
+ configSet = append(configSet, setPrefixPolicyPermitAppSvc+"ssl-proxy")
+ }
+ } else {
+ configSet = append(configSet, setPrefixPolicyPermitAppSvc+"ssl-proxy")
+ }
+ }
+ if len(policyPermitApplicationServices["uac_policy"].([]interface{})) > 0 {
+ if policyPermitApplicationServices["uac_policy"].([]interface{})[0] != nil {
+ policyPermitApplicationServicesUACPolicy :=
+ policyPermitApplicationServices["uac_policy"].([]interface{})[0].(map[string]interface{})
+ if policyPermitApplicationServicesUACPolicy["captive_portal"].(string) != "" {
+ configSet = append(configSet, setPrefixPolicyPermitAppSvc+
+ "uac-policy captive-portal \""+
+ policyPermitApplicationServicesUACPolicy["captive_portal"].(string)+"\"")
+ } else {
+ configSet = append(configSet, setPrefixPolicyPermitAppSvc+"uac-policy")
+ }
+ } else {
+ configSet = append(configSet, setPrefixPolicyPermitAppSvc+"uac-policy")
+ }
+ }
+ if policyPermitApplicationServices["utm_policy"].(string) != "" {
+ configSet = append(configSet, setPrefixPolicyPermitAppSvc+
+ "utm-policy \""+policyPermitApplicationServices["utm_policy"].(string)+"\"")
+ }
+
+ return configSet, nil
+}
diff --git a/junos/resource_security_global_policy_test.go b/junos/resource_security_global_policy_test.go
new file mode 100644
index 00000000..e6cf02bf
--- /dev/null
+++ b/junos/resource_security_global_policy_test.go
@@ -0,0 +1,131 @@
+package junos_test
+
+import (
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+)
+
+func TestAccJunosSecurityGlobalPolicy_basic(t *testing.T) {
+ if os.Getenv("TESTACC_SWITCH") == "" {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ Providers: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccJunosSecurityGlobalPolicyConfigCreate(),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("junos_security_global_policy.testacc_secglobpolicy",
+ "policy.#", "1"),
+ resource.TestCheckResourceAttr("junos_security_global_policy.testacc_secglobpolicy",
+ "policy.0.name", "test"),
+ resource.TestCheckResourceAttr("junos_security_global_policy.testacc_secglobpolicy",
+ "policy.0.then", "permit"),
+ ),
+ },
+ {
+ Config: testAccJunosSecurityGlobalPolicyConfigUpdate(),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("junos_security_global_policy.testacc_secglobpolicy",
+ "policy.#", "2"),
+ resource.TestCheckResourceAttr("junos_security_global_policy.testacc_secglobpolicy",
+ "policy.0.permit_application_services.#", "1"),
+ resource.TestCheckResourceAttr("junos_security_global_policy.testacc_secglobpolicy",
+ "policy.1.then", "deny"),
+ ),
+ },
+ {
+ ResourceName: "junos_security_global_policy.testacc_secglobpolicy",
+ ImportState: true,
+ ImportStateVerify: true,
+ },
+ },
+ })
+ }
+}
+
+func testAccJunosSecurityGlobalPolicyConfigCreate() string {
+ return `
+resource junos_security_zone "testacc_secglobpolicy1" {
+ name = "testacc_secglobpolicy1"
+}
+resource junos_security_zone "testacc_secglobpolicy2" {
+ name = "testacc_secglobpolicy2"
+}
+resource "junos_security_address_book" "testacc_secglobpolicy" {
+ network_address {
+ name = "blue"
+ value = "192.0.2.1/32"
+ }
+ network_address {
+ name = "green"
+ value = "192.0.2.2/32"
+ }
+}
+resource junos_security_global_policy "testacc_secglobpolicy" {
+ depends_on = [
+ junos_security_address_book.testacc_secglobpolicy
+ ]
+ policy {
+ name = "test"
+ match_source_address = ["blue"]
+ match_destination_address = ["green"]
+ match_application = ["any"]
+ match_from_zone = [junos_security_zone.testacc_secglobpolicy1.name]
+ match_to_zone = [junos_security_zone.testacc_secglobpolicy2.name]
+ }
+}
+`
+}
+func testAccJunosSecurityGlobalPolicyConfigUpdate() string {
+ return `
+resource junos_security_zone "testacc_secglobpolicy1" {
+ name = "testacc_secglobpolicy1"
+}
+resource junos_security_zone "testacc_secglobpolicy2" {
+ name = "testacc_secglobpolicy2"
+}
+resource "junos_security_address_book" "testacc_secglobpolicy" {
+ network_address {
+ name = "blue"
+ value = "192.0.2.1/32"
+ }
+ network_address {
+ name = "green"
+ value = "192.0.2.2/32"
+ }
+}
+resource junos_security_global_policy "testacc_secglobpolicy" {
+ depends_on = [
+ junos_security_address_book.testacc_secglobpolicy
+ ]
+ policy {
+ name = "test"
+ match_source_address = ["blue"]
+ match_destination_address = ["any"]
+ match_application = ["any"]
+ match_from_zone = [junos_security_zone.testacc_secglobpolicy1.name]
+ match_to_zone = [junos_security_zone.testacc_secglobpolicy1.name]
+ count = true
+ log_init = true
+ log_close = true
+ permit_application_services {
+ idp = true
+ redirect_wx = true
+ ssl_proxy {}
+ uac_policy {}
+ }
+ }
+ policy {
+ name = "drop"
+ match_source_address = ["blue"]
+ match_destination_address = ["any"]
+ match_application = ["any"]
+ match_from_zone = ["any"]
+ match_to_zone = ["any"]
+ then = "deny"
+ }
+}
+`
+}
diff --git a/junos/resource_security_ike_gateway.go b/junos/resource_security_ike_gateway.go
index 58edf2b4..2cb669f5 100644
--- a/junos/resource_security_ike_gateway.go
+++ b/junos/resource_security_ike_gateway.go
@@ -42,7 +42,7 @@ func resourceIkeGateway() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"external_interface": {
Type: schema.TypeString,
@@ -160,7 +160,7 @@ func resourceIkeGateway() *schema.Resource {
"access_profile": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
ConflictsWith: []string{
"aaa.0.client_password",
"aaa.0.client_username",
@@ -272,6 +272,14 @@ func resourceIkeGateway() *schema.Resource {
func resourceIkeGatewayCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setIkeGateway(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -561,11 +569,7 @@ func setIkeGateway(d *schema.ResourceData, m interface{}, jnprSess *NetconfObjec
configSet = append(configSet, setPrefix+" version "+d.Get("version").(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readIkeGateway(ikeGateway string, m interface{}, jnprSess *NetconfObject) (ikeGatewayOptions, error) {
sess := m.(*Session)
@@ -738,11 +742,8 @@ func delIkeGateway(d *schema.ResourceData, m interface{}, jnprSess *NetconfObjec
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security ike gateway "+d.Get("name").(string))
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillIkeGatewayData(d *schema.ResourceData, ikeGatewayOptions ikeGatewayOptions) {
diff --git a/junos/resource_security_ike_policy.go b/junos/resource_security_ike_policy.go
index b2441d80..83dc0368 100644
--- a/junos/resource_security_ike_policy.go
+++ b/junos/resource_security_ike_policy.go
@@ -46,7 +46,7 @@ func resourceIkePolicy() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"proposals": {
Type: schema.TypeList,
@@ -85,6 +85,14 @@ func resourceIkePolicy() *schema.Resource {
func resourceIkePolicyCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setIkePolicy(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -274,11 +282,7 @@ func setIkePolicy(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject
configSet = append(configSet, setPrefix+" pre-shared-key hexadecimal "+d.Get("pre_shared_key_hexa").(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readIkePolicy(ikePolicy string, m interface{}, jnprSess *NetconfObject) (ikePolicyOptions, error) {
sess := m.(*Session)
@@ -328,11 +332,8 @@ func delIkePolicy(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security ike policy "+d.Get("name").(string))
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillIkePolicyData(d *schema.ResourceData, ikePolicyOptions ikePolicyOptions) {
diff --git a/junos/resource_security_ike_proposal.go b/junos/resource_security_ike_proposal.go
index 857c4989..3bc77fac 100644
--- a/junos/resource_security_ike_proposal.go
+++ b/junos/resource_security_ike_proposal.go
@@ -34,7 +34,7 @@ func resourceIkeProposal() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"authentication_algorithm": {
Type: schema.TypeString,
@@ -64,6 +64,14 @@ func resourceIkeProposal() *schema.Resource {
func resourceIkeProposalCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setIkeProposal(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -250,11 +258,7 @@ func setIkeProposal(d *schema.ResourceData, m interface{}, jnprSess *NetconfObje
configSet = append(configSet, setPrefix+" lifetime-seconds "+strconv.Itoa(d.Get("lifetime_seconds").(int)))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readIkeProposal(ikeProposal string, m interface{}, jnprSess *NetconfObject) (ikeProposalOptions, error) {
sess := m.(*Session)
@@ -299,11 +303,8 @@ func delIkeProposal(d *schema.ResourceData, m interface{}, jnprSess *NetconfObje
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security ike proposal "+d.Get("name").(string))
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillIkeProposalData(d *schema.ResourceData, ikeProposalOptions ikeProposalOptions) {
diff --git a/junos/resource_security_ipsec_policy.go b/junos/resource_security_ipsec_policy.go
index 93643a99..71d93519 100644
--- a/junos/resource_security_ipsec_policy.go
+++ b/junos/resource_security_ipsec_policy.go
@@ -31,7 +31,7 @@ func resourceIpsecPolicy() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"pfs_keys": {
Type: schema.TypeString,
@@ -56,6 +56,14 @@ func resourceIpsecPolicy() *schema.Resource {
func resourceIpsecPolicyCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setIpsecPolicy(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -236,11 +244,7 @@ func setIpsecPolicy(d *schema.ResourceData, m interface{}, jnprSess *NetconfObje
configSet = append(configSet, setPrefix+" proposal-set "+d.Get("proposal_set").(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readIpsecPolicy(ipsecPolicy string, m interface{}, jnprSess *NetconfObject) (ipsecPolicyOptions, error) {
sess := m.(*Session)
@@ -278,11 +282,8 @@ func delIpsecPolicy(d *schema.ResourceData, m interface{}, jnprSess *NetconfObje
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security ipsec policy "+d.Get("name").(string))
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillIpsecPolicyData(d *schema.ResourceData, ipsecPolicyOptions ipsecPolicyOptions) {
diff --git a/junos/resource_security_ipsec_proposal.go b/junos/resource_security_ipsec_proposal.go
index 3fbb22c2..ef8fe918 100644
--- a/junos/resource_security_ipsec_proposal.go
+++ b/junos/resource_security_ipsec_proposal.go
@@ -34,7 +34,7 @@ func resourceIpsecProposal() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"authentication_algorithm": {
Type: schema.TypeString,
@@ -65,6 +65,14 @@ func resourceIpsecProposal() *schema.Resource {
func resourceIpsecProposalCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setIpsecProposal(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -252,11 +260,7 @@ func setIpsecProposal(d *schema.ResourceData, m interface{}, jnprSess *NetconfOb
configSet = append(configSet, setPrefix+" protocol "+d.Get("protocol").(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readIpsecProposal(ipsecProposal string, m interface{}, jnprSess *NetconfObject) (ipsecProposalOptions, error) {
sess := m.(*Session)
@@ -304,11 +308,8 @@ func delIpsecProposal(d *schema.ResourceData, m interface{}, jnprSess *NetconfOb
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security ipsec proposal "+d.Get("name").(string))
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillIpsecProposalData(d *schema.ResourceData, ipsecProposalOptions ipsecProposalOptions) {
diff --git a/junos/resource_security_ipsec_vpn.go b/junos/resource_security_ipsec_vpn.go
index 4a6c181c..e1e049c8 100644
--- a/junos/resource_security_ipsec_vpn.go
+++ b/junos/resource_security_ipsec_vpn.go
@@ -35,7 +35,7 @@ func resourceIpsecVpn() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"bind_interface": {
Type: schema.TypeString,
@@ -71,7 +71,7 @@ func resourceIpsecVpn() *schema.Resource {
"policy": {
Type: schema.TypeString,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"identity_local": {
Type: schema.TypeString,
@@ -86,7 +86,7 @@ func resourceIpsecVpn() *schema.Resource {
"identity_service": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
},
},
@@ -100,7 +100,7 @@ func resourceIpsecVpn() *schema.Resource {
"name": {
Type: schema.TypeString,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"local_ip": {
Type: schema.TypeString,
@@ -148,6 +148,14 @@ func resourceIpsecVpn() *schema.Resource {
func resourceIpsecVpnCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" && !d.Get("bind_interface_auto").(bool) {
+ if err := setIpsecVpn(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -174,7 +182,7 @@ func resourceIpsecVpnCreate(ctx context.Context, d *schema.ResourceData, m inter
if err != nil {
sess.configClear(jnprSess)
- return diag.FromErr(fmt.Errorf("error for find new bind interface: %w", err))
+ return diag.FromErr(fmt.Errorf("error for find new bind interface : %w", err))
}
tfErr := d.Set("bind_interface", newSt0)
if tfErr != nil {
@@ -416,11 +424,7 @@ func setIpsecVpn(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject)
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readIpsecVpn(ipsecVpn string, m interface{}, jnprSess *NetconfObject) (ipsecVpnOptions, error) {
sess := m.(*Session)
@@ -524,11 +528,8 @@ func delIpsecVpnConf(d *schema.ResourceData, m interface{}, jnprSess *NetconfObj
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security ipsec vpn "+d.Get("name").(string))
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func delIpsecVpn(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
@@ -543,11 +544,8 @@ func delIpsecVpn(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject)
configSet = append(configSet, "delete interfaces "+d.Get("bind_interface").(string))
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillIpsecVpnData(d *schema.ResourceData, ipsecVpnOptions ipsecVpnOptions) {
diff --git a/junos/resource_security_log_stream.go b/junos/resource_security_log_stream.go
index 07a98046..85fe59af 100644
--- a/junos/resource_security_log_stream.go
+++ b/junos/resource_security_log_stream.go
@@ -102,7 +102,7 @@ func resourceSecurityLogStream() *schema.Resource {
"routing_instance": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{"default"}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{"default"}, 64, FormatDefault),
},
},
},
@@ -123,6 +123,14 @@ func resourceSecurityLogStream() *schema.Resource {
func resourceSecurityLogStreamCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSecurityLogStream(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -339,11 +347,7 @@ func setSecurityLogStream(d *schema.ResourceData, m interface{}, jnprSess *Netco
d.Get("severity").(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readSecurityLogStream(securityLogStream string, m interface{}, jnprSess *NetconfObject) (
securityLogStreamOptions, error) {
@@ -438,11 +442,8 @@ func delLogStream(securityLogStream string, m interface{}, jnprSess *NetconfObje
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security log stream \""+securityLogStream+"\"")
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillSecurityLogStreamData(d *schema.ResourceData, securityLogStreamOptions securityLogStreamOptions) {
diff --git a/junos/resource_security_nat_destination.go b/junos/resource_security_nat_destination.go
index 98814f03..bf1d15b1 100644
--- a/junos/resource_security_nat_destination.go
+++ b/junos/resource_security_nat_destination.go
@@ -30,7 +30,7 @@ func resourceSecurityNatDestination() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"from": {
Type: schema.TypeList,
@@ -60,7 +60,7 @@ func resourceSecurityNatDestination() *schema.Resource {
"name": {
Type: schema.TypeString,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"destination_address": {
Type: schema.TypeString,
@@ -81,7 +81,7 @@ func resourceSecurityNatDestination() *schema.Resource {
"pool": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
},
},
@@ -95,6 +95,14 @@ func resourceSecurityNatDestination() *schema.Resource {
func resourceSecurityNatDestinationCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSecurityNatDestination(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -294,11 +302,8 @@ func setSecurityNatDestination(d *schema.ResourceData, m interface{}, jnprSess *
}
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readSecurityNatDestination(natDestination string,
m interface{}, jnprSess *NetconfObject) (natDestinationOptions, error) {
@@ -380,11 +385,8 @@ func delSecurityNatDestination(natDestination string, m interface{}, jnprSess *N
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security nat destination rule-set "+natDestination)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillSecurityNatDestinationData(d *schema.ResourceData, natDestinationOptions natDestinationOptions) {
if tfErr := d.Set("name", natDestinationOptions.name); tfErr != nil {
diff --git a/junos/resource_security_nat_destination_pool.go b/junos/resource_security_nat_destination_pool.go
index acd0973c..629c39e1 100644
--- a/junos/resource_security_nat_destination_pool.go
+++ b/junos/resource_security_nat_destination_pool.go
@@ -33,7 +33,7 @@ func resourceSecurityNatDestinationPool() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"address": {
Type: schema.TypeString,
@@ -55,7 +55,7 @@ func resourceSecurityNatDestinationPool() *schema.Resource {
"routing_instance": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
},
}
@@ -64,6 +64,14 @@ func resourceSecurityNatDestinationPool() *schema.Resource {
func resourceSecurityNatDestinationPoolCreate(
ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSecurityNatDestinationPool(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -251,11 +259,8 @@ func setSecurityNatDestinationPool(d *schema.ResourceData, m interface{}, jnprSe
if d.Get("routing_instance").(string) != "" {
configSet = append(configSet, setPrefix+" routing-instance "+d.Get("routing_instance").(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readSecurityNatDestinationPool(natDestinationPool string,
m interface{}, jnprSess *NetconfObject) (natDestinationPoolOptions, error) {
@@ -300,11 +305,8 @@ func delSecurityNatDestinationPool(natDestinationPool string, m interface{}, jnp
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security nat destination pool "+natDestinationPool)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillSecurityNatDestinationPoolData(d *schema.ResourceData, natDestinationPoolOptions natDestinationPoolOptions) {
if tfErr := d.Set("name", natDestinationPoolOptions.name); tfErr != nil {
diff --git a/junos/resource_security_nat_source.go b/junos/resource_security_nat_source.go
index 9b6d05b0..069b6d8d 100644
--- a/junos/resource_security_nat_source.go
+++ b/junos/resource_security_nat_source.go
@@ -31,7 +31,7 @@ func resourceSecurityNatSource() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"from": {
Type: schema.TypeList,
@@ -81,7 +81,7 @@ func resourceSecurityNatSource() *schema.Resource {
"name": {
Type: schema.TypeString,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"match": {
Type: schema.TypeList,
@@ -121,7 +121,7 @@ func resourceSecurityNatSource() *schema.Resource {
"pool": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
},
},
@@ -135,6 +135,14 @@ func resourceSecurityNatSource() *schema.Resource {
func resourceSecurityNatSourceCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSecurityNatSource(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -361,11 +369,8 @@ func setSecurityNatSource(d *schema.ResourceData, m interface{}, jnprSess *Netco
}
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readSecurityNatSource(natSource string, m interface{}, jnprSess *NetconfObject) (natSourceOptions, error) {
sess := m.(*Session)
@@ -483,11 +488,8 @@ func delSecurityNatSource(natSource string, m interface{}, jnprSess *NetconfObje
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security nat source rule-set "+natSource)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillSecurityNatSourceData(d *schema.ResourceData, natSourceOptions natSourceOptions) {
if tfErr := d.Set("name", natSourceOptions.name); tfErr != nil {
diff --git a/junos/resource_security_nat_source_pool.go b/junos/resource_security_nat_source_pool.go
index 7d97442a..a7aeee91 100644
--- a/junos/resource_security_nat_source_pool.go
+++ b/junos/resource_security_nat_source_pool.go
@@ -35,7 +35,7 @@ func resourceSecurityNatSourcePool() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"address": {
Type: schema.TypeList,
@@ -63,7 +63,7 @@ func resourceSecurityNatSourcePool() *schema.Resource {
"routing_instance": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
},
}
@@ -71,6 +71,14 @@ func resourceSecurityNatSourcePool() *schema.Resource {
func resourceSecurityNatSourcePoolCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSecurityNatSourcePool(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -267,11 +275,8 @@ func setSecurityNatSourcePool(d *schema.ResourceData, m interface{}, jnprSess *N
if d.Get("routing_instance").(string) != "" {
configSet = append(configSet, setPrefix+" routing-instance "+d.Get("routing_instance").(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readSecurityNatSourcePool(natSourcePool string,
m interface{}, jnprSess *NetconfObject) (natSourcePoolOptions, error) {
@@ -323,11 +328,8 @@ func delSecurityNatSourcePool(natSourcePool string, m interface{}, jnprSess *Net
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security nat source pool "+natSourcePool)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillSecurityNatSourcePoolData(d *schema.ResourceData, natSourcePoolOptions natSourcePoolOptions) {
if tfErr := d.Set("name", natSourcePoolOptions.name); tfErr != nil {
diff --git a/junos/resource_security_nat_static.go b/junos/resource_security_nat_static.go
index 362eeb33..1641e213 100644
--- a/junos/resource_security_nat_static.go
+++ b/junos/resource_security_nat_static.go
@@ -30,7 +30,7 @@ func resourceSecurityNatStatic() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"from": {
Type: schema.TypeList,
@@ -59,7 +59,7 @@ func resourceSecurityNatStatic() *schema.Resource {
"name": {
Type: schema.TypeString,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"destination_address": {
Type: schema.TypeString,
@@ -85,7 +85,7 @@ func resourceSecurityNatStatic() *schema.Resource {
"routing_instance": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
},
},
@@ -99,6 +99,14 @@ func resourceSecurityNatStatic() *schema.Resource {
func resourceSecurityNatStaticCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSecurityNatStatic(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -307,11 +315,8 @@ func setSecurityNatStatic(d *schema.ResourceData, m interface{}, jnprSess *Netco
}
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readSecurityNatStatic(natStatic string, m interface{}, jnprSess *NetconfObject) (natStaticOptions, error) {
sess := m.(*Session)
@@ -399,11 +404,8 @@ func delSecurityNatStatic(natStatic string, m interface{}, jnprSess *NetconfObje
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security nat static rule-set "+natStatic)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillSecurityNatStaticData(d *schema.ResourceData, natStaticOptions natStaticOptions) {
if tfErr := d.Set("name", natStaticOptions.name); tfErr != nil {
diff --git a/junos/resource_security_policy.go b/junos/resource_security_policy.go
index e5e4a846..f8df4a7d 100644
--- a/junos/resource_security_policy.go
+++ b/junos/resource_security_policy.go
@@ -30,13 +30,13 @@ func resourceSecurityPolicy() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"to_zone": {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"policy": {
Type: schema.TypeList,
@@ -46,7 +46,7 @@ func resourceSecurityPolicy() *schema.Resource {
"name": {
Type: schema.TypeString,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"match_source_address": {
Type: schema.TypeList,
@@ -165,6 +165,14 @@ func resourceSecurityPolicy() *schema.Resource {
func resourceSecurityPolicyCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSecurityPolicy(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("from_zone").(string) + idSeparator + d.Get("to_zone").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -409,11 +417,8 @@ func setSecurityPolicy(d *schema.ResourceData, m interface{}, jnprSess *NetconfO
configSet = append(configSet, configSetAppSvc...)
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readSecurityPolicy(idPolicy string, m interface{}, jnprSess *NetconfObject) (policyOptions, error) {
zone := strings.Split(idPolicy, idSeparator)
@@ -489,11 +494,8 @@ func delSecurityPolicy(fromZone string, toZone string, m interface{}, jnprSess *
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security policies from-zone "+fromZone+" to-zone "+toZone)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillSecurityPolicyData(d *schema.ResourceData, policyOptions policyOptions) {
diff --git a/junos/resource_security_policy_tunnel_pair_policy.go b/junos/resource_security_policy_tunnel_pair_policy.go
index 01aaa506..4a7dfd49 100644
--- a/junos/resource_security_policy_tunnel_pair_policy.go
+++ b/junos/resource_security_policy_tunnel_pair_policy.go
@@ -29,25 +29,25 @@ func resourceSecurityPolicyTunnelPairPolicy() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"zone_b": {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"policy_a_to_b": {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"policy_b_to_a": {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
},
}
@@ -56,6 +56,15 @@ func resourceSecurityPolicyTunnelPairPolicy() *schema.Resource {
func resourceSecurityPolicyTunnelPairPolicyCreate(
ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSecurityPolicyTunnelPairPolicy(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("zone_a").(string) + idSeparator + d.Get("policy_a_to_b").(string) +
+ idSeparator + d.Get("zone_b").(string) + idSeparator + d.Get("policy_b_to_a").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -256,11 +265,7 @@ func setSecurityPolicyTunnelPairPolicy(d *schema.ResourceData, m interface{}, jn
" policy "+d.Get("policy_b_to_a").(string)+
" then permit tunnel pair-policy "+d.Get("policy_a_to_b").(string))
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readSecurityPolicyTunnelPairPolicy(idRessource string,
m interface{}, jnprSess *NetconfObject) (policyPairPolicyOptions, error) {
@@ -333,11 +338,8 @@ func delSecurityPolicyTunnelPairPolicy(d *schema.ResourceData, m interface{}, jn
" from-zone "+d.Get("zone_b").(string)+" to-zone "+d.Get("zone_a").(string)+
" policy "+d.Get("policy_b_to_a").(string)+
" then permit tunnel pair-policy "+d.Get("policy_a_to_b").(string))
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillSecurityPolicyPairData(d *schema.ResourceData, policyPairPolicyOptions policyPairPolicyOptions) {
diff --git a/junos/resource_security_screen.go b/junos/resource_security_screen.go
index 1dde4af9..84babcc7 100644
--- a/junos/resource_security_screen.go
+++ b/junos/resource_security_screen.go
@@ -476,7 +476,7 @@ func resourceSecurityScreen() *schema.Resource {
"name": {
Type: schema.TypeString,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"destination_address": {
Type: schema.TypeList,
@@ -581,6 +581,14 @@ func resourceSecurityScreen() *schema.Resource {
func resourceSecurityScreenCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSecurityScreen(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -817,11 +825,7 @@ func setSecurityScreen(d *schema.ResourceData, m interface{}, jnprSess *NetconfO
configSet = append(configSet, setSecurityScreenUDP(udp, setPrefix)...)
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func setSecurityScreenIcmp(icmp map[string]interface{}, setPrefix string) []string {
configSet := make([]string, 0)
@@ -1804,11 +1808,8 @@ func delSecurityScreen(name string, m interface{}, jnprSess *NetconfObject) erro
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security screen ids-option \""+name+"\"")
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillSecurityScreenData(d *schema.ResourceData, screenOptions screenOptions) {
diff --git a/junos/resource_security_screen_whitelist.go b/junos/resource_security_screen_whitelist.go
index 8848a767..8e17ad02 100644
--- a/junos/resource_security_screen_whitelist.go
+++ b/junos/resource_security_screen_whitelist.go
@@ -28,7 +28,7 @@ func resourceSecurityScreenWhiteList() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"address": {
Type: schema.TypeList,
@@ -42,6 +42,14 @@ func resourceSecurityScreenWhiteList() *schema.Resource {
func resourceSecurityScreenWhiteListCreate(
ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSecurityScreenWhiteList(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -228,11 +236,7 @@ func setSecurityScreenWhiteList(d *schema.ResourceData, m interface{}, jnprSess
configSet = append(configSet, setPrefix+"address "+v.(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readSecurityScreenWhiteList(name string, m interface{}, jnprSess *NetconfObject) (screenWhiteListOptions, error) {
@@ -267,11 +271,8 @@ func delSecurityScreenWhiteList(name string, m interface{}, jnprSess *NetconfObj
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security screen white-list "+name)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillSecurityScreenWhiteListData(d *schema.ResourceData, whiteListOptions screenWhiteListOptions) {
diff --git a/junos/resource_security_test.go b/junos/resource_security_test.go
index ccbbf0fb..ec20ec71 100644
--- a/junos/resource_security_test.go
+++ b/junos/resource_security_test.go
@@ -374,6 +374,10 @@ resource junos_security "testacc_security" {
}
utm {
feature_profile_web_filtering_type = "juniper-enhanced"
+ feature_profile_web_filtering_juniper_enhanced_server {
+ host = "192.0.2.1"
+ port = 1500
+ }
}
}
`
@@ -430,6 +434,17 @@ resource junos_security "testacc_security" {
rate_cap = 100
source_address = "192.0.2.1"
}
+ utm {
+ feature_profile_web_filtering_type = "juniper-enhanced"
+ feature_profile_web_filtering_juniper_enhanced_server {
+ host = "192.0.2.1"
+ port = 1500
+ routing_instance = junos_routing_instance.testacc_security.name
+ }
+ }
+}
+resource junos_routing_instance testacc_security {
+ name = "testacc_security"
}
`
}
diff --git a/junos/resource_security_utm_custom_url_category.go b/junos/resource_security_utm_custom_url_category.go
index a39f3a48..39f372c7 100644
--- a/junos/resource_security_utm_custom_url_category.go
+++ b/junos/resource_security_utm_custom_url_category.go
@@ -28,7 +28,7 @@ func resourceSecurityUtmCustomURLCategory() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"value": {
Type: schema.TypeList,
@@ -43,6 +43,14 @@ func resourceSecurityUtmCustomURLCategory() *schema.Resource {
func resourceSecurityUtmCustomURLCategoryCreate(
ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setUtmCustomURLCategory(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -225,11 +233,7 @@ func setUtmCustomURLCategory(d *schema.ResourceData, m interface{}, jnprSess *Ne
configSet = append(configSet, setPrefix+"value "+v.(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readUtmCustomURLCategory(urlCategory string, m interface{}, jnprSess *NetconfObject) (
utmCustomURLCategoryOptions, error) {
@@ -264,11 +268,8 @@ func delUtmCustomURLCategory(urlCategory string, m interface{}, jnprSess *Netcon
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security utm custom-objects custom-url-category "+urlCategory)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillUtmCustomURLCategoryData(d *schema.ResourceData, utmCustomURLCategoryOptions utmCustomURLCategoryOptions) {
diff --git a/junos/resource_security_utm_custom_url_pattern.go b/junos/resource_security_utm_custom_url_pattern.go
index d092cbd9..0e6c2769 100644
--- a/junos/resource_security_utm_custom_url_pattern.go
+++ b/junos/resource_security_utm_custom_url_pattern.go
@@ -28,7 +28,7 @@ func resourceSecurityUtmCustomURLPattern() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"value": {
Type: schema.TypeList,
@@ -43,6 +43,14 @@ func resourceSecurityUtmCustomURLPattern() *schema.Resource {
func resourceSecurityUtmCustomURLPatternCreate(
ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setUtmCustomURLPattern(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -223,11 +231,7 @@ func setUtmCustomURLPattern(d *schema.ResourceData, m interface{}, jnprSess *Net
configSet = append(configSet, setPrefix+"value "+v.(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readUtmCustomURLPattern(urlPattern string, m interface{}, jnprSess *NetconfObject) (
utmCustomURLPatternOptions, error) {
@@ -262,11 +266,8 @@ func delUtmCustomURLPattern(urlPattern string, m interface{}, jnprSess *NetconfO
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security utm custom-objects url-pattern "+urlPattern)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillUtmCustomURLPatternData(d *schema.ResourceData, utmCustomURLPatternOptions utmCustomURLPatternOptions) {
diff --git a/junos/resource_security_utm_policy.go b/junos/resource_security_utm_policy.go
index 33f14654..31c4d00b 100644
--- a/junos/resource_security_utm_policy.go
+++ b/junos/resource_security_utm_policy.go
@@ -135,6 +135,14 @@ func resourceSecurityUtmPolicy() *schema.Resource {
func resourceSecurityUtmPolicyCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setUtmPolicy(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -395,11 +403,7 @@ func setUtmPolicy(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject
d.Get("web_filtering_profile").(string)+"\"")
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readUtmPolicy(policy string, m interface{}, jnprSess *NetconfObject) (
utmPolicyOptions, error) {
@@ -499,11 +503,8 @@ func delUtmPolicy(policy string, m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security utm utm-policy \""+policy+"\"")
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillUtmPolicyData(d *schema.ResourceData, utmPolicyOptions utmPolicyOptions) {
diff --git a/junos/resource_security_utm_profile_web_filtering_juniper_enhanced.go b/junos/resource_security_utm_profile_web_filtering_juniper_enhanced.go
index 6f9c5ce3..6c807bd7 100644
--- a/junos/resource_security_utm_profile_web_filtering_juniper_enhanced.go
+++ b/junos/resource_security_utm_profile_web_filtering_juniper_enhanced.go
@@ -65,7 +65,7 @@ func resourceSecurityUtmProfileWebFilteringEnhanced() *schema.Resource {
"name": {
Type: schema.TypeString,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 128),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 128, FormatDefault),
},
"action": {
Type: schema.TypeString,
@@ -188,6 +188,14 @@ func resourceSecurityUtmProfileWebFilteringEnhanced() *schema.Resource {
func resourceSecurityUtmProfileWebFilteringEnhancedCreate(
ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setUtmProfileWebFEnhanced(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -449,11 +457,7 @@ func setUtmProfileWebFEnhanced(d *schema.ResourceData, m interface{}, jnprSess *
configSet = append(configSet, setPrefix+"timeout "+strconv.Itoa(d.Get("timeout").(int)))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readUtmProfileWebFEnhanced(profile string, m interface{}, jnprSess *NetconfObject) (
utmProfileWebFilteringEnhancedOptions, error) {
@@ -576,11 +580,8 @@ func delUtmProfileWebFEnhanced(profile string, m interface{}, jnprSess *NetconfO
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security utm feature-profile web-filtering juniper-enhanced "+
"profile \""+profile+"\"")
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillUtmProfileWebFEnhancedData(d *schema.ResourceData,
diff --git a/junos/resource_security_utm_profile_web_filtering_juniper_local.go b/junos/resource_security_utm_profile_web_filtering_juniper_local.go
index 3d13160d..2fdbce65 100644
--- a/junos/resource_security_utm_profile_web_filtering_juniper_local.go
+++ b/junos/resource_security_utm_profile_web_filtering_juniper_local.go
@@ -84,6 +84,14 @@ func resourceSecurityUtmProfileWebFilteringLocal() *schema.Resource {
func resourceSecurityUtmProfileWebFilteringLocalCreate(
ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setUtmProfileWebFLocal(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -297,11 +305,7 @@ func setUtmProfileWebFLocal(d *schema.ResourceData, m interface{}, jnprSess *Net
configSet = append(configSet, setPrefix+"timeout "+strconv.Itoa(d.Get("timeout").(int)))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readUtmProfileWebFLocal(profile string, m interface{}, jnprSess *NetconfObject) (
utmProfileWebFilteringLocalOptions, error) {
@@ -366,11 +370,8 @@ func delUtmProfileWebFLocal(profile string, m interface{}, jnprSess *NetconfObje
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security utm feature-profile web-filtering juniper-local "+
"profile \""+profile+"\"")
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillUtmProfileWebFLocalData(d *schema.ResourceData,
diff --git a/junos/resource_security_utm_profile_web_filtering_websense_redirect.go b/junos/resource_security_utm_profile_web_filtering_websense_redirect.go
index 47e81b4c..8e9db35e 100644
--- a/junos/resource_security_utm_profile_web_filtering_websense_redirect.go
+++ b/junos/resource_security_utm_profile_web_filtering_websense_redirect.go
@@ -108,6 +108,14 @@ func resourceSecurityUtmProfileWebFilteringWebsense() *schema.Resource {
func resourceSecurityUtmProfileWebFilteringWebsenseCreate(
ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setUtmProfileWebFWebsense(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -338,11 +346,7 @@ func setUtmProfileWebFWebsense(d *schema.ResourceData, m interface{}, jnprSess *
configSet = append(configSet, setPrefix+"timeout "+strconv.Itoa(d.Get("timeout").(int)))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readUtmProfileWebFWebsense(profile string, m interface{}, jnprSess *NetconfObject) (
utmProfileWebFilteringWebsenseOptions, error) {
@@ -430,11 +434,8 @@ func delUtmProfileWebFWebsense(profile string, m interface{}, jnprSess *NetconfO
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security utm feature-profile web-filtering websense-redirect "+
"profile \""+profile+"\"")
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillUtmProfileWebFWebsenseData(d *schema.ResourceData,
diff --git a/junos/resource_security_zone.go b/junos/resource_security_zone.go
index 306e1e99..11c63283 100644
--- a/junos/resource_security_zone.go
+++ b/junos/resource_security_zone.go
@@ -39,7 +39,7 @@ func resourceSecurityZone() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"address_book": {
Type: schema.TypeList,
@@ -49,7 +49,7 @@ func resourceSecurityZone() *schema.Resource {
"name": {
Type: schema.TypeString,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatAddressName),
},
"network": {
Type: schema.TypeString,
@@ -67,7 +67,7 @@ func resourceSecurityZone() *schema.Resource {
"name": {
Type: schema.TypeString,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatAddressName),
},
"address": {
Type: schema.TypeList,
@@ -122,6 +122,14 @@ func resourceSecurityZone() *schema.Resource {
func resourceSecurityZoneCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSecurityZone(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -337,11 +345,7 @@ func setSecurityZone(d *schema.ResourceData, m interface{}, jnprSess *NetconfObj
configSet = append(configSet, setPrefix+" tcp-rst")
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readSecurityZone(zone string, m interface{}, jnprSess *NetconfObject) (zoneOptions, error) {
sess := m.(*Session)
@@ -433,21 +437,15 @@ func delSecurityZoneOpts(zone string, m interface{}, jnprSess *NetconfObject) er
for _, line := range listLinesToDelete {
configSet = append(configSet, delPrefix+line)
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func delSecurityZone(zone string, m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete security zones security-zone "+zone)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillSecurityZoneData(d *schema.ResourceData, zoneOptions zoneOptions) {
diff --git a/junos/resource_static_route.go b/junos/resource_static_route.go
index 25f2cc69..848bd1de 100644
--- a/junos/resource_static_route.go
+++ b/junos/resource_static_route.go
@@ -56,7 +56,7 @@ func resourceStaticRoute() *schema.Resource {
Optional: true,
ForceNew: true,
Default: defaultWord,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"active": {
Type: schema.TypeBool,
@@ -178,6 +178,14 @@ func resourceStaticRoute() *schema.Resource {
func resourceStaticRouteCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setStaticRoute(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("destination").(string) + idSeparator + d.Get("routing_instance").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -485,11 +493,8 @@ func setStaticRoute(d *schema.ResourceData, m interface{}, jnprSess *NetconfObje
if d.Get("no_retain").(bool) {
configSet = append(configSet, setPrefix+" no-retain")
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readStaticRoute(destination string, instance string, m interface{},
jnprSess *NetconfObject) (staticRouteOptions, error) {
@@ -655,11 +660,8 @@ func delStaticRouteOpts(d *schema.ResourceData, m interface{}, jnprSess *Netconf
configSet = append(configSet, delPrefix+"qualified-next-hop "+qualifiedNextHop["next_hop"].(string))
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func delStaticRoute(destination string, instance string, m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
@@ -678,11 +680,8 @@ func delStaticRoute(destination string, instance string, m interface{}, jnprSess
" routing-options rib "+instance+".inet6.0 static route "+destination)
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillStaticRouteData(d *schema.ResourceData, staticRouteOptions staticRouteOptions) {
diff --git a/junos/resource_system.go b/junos/resource_system.go
index 18d1c5bc..bba97c9f 100644
--- a/junos/resource_system.go
+++ b/junos/resource_system.go
@@ -591,6 +591,14 @@ func resourceSystem() *schema.Resource {
func resourceSystemCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSystem(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId("system")
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -803,11 +811,7 @@ func setSystem(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) e
d.Get("tracing_dest_override_syslog_host").(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func setSystemServices(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
@@ -898,11 +902,8 @@ func setSystemServices(d *schema.ResourceData, m interface{}, jnprSess *NetconfO
}
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func setSystemInternetOptions(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
@@ -1007,11 +1008,8 @@ func setSystemInternetOptions(d *schema.ResourceData, m interface{}, jnprSess *N
configSet = append(configSet, setPrefix+"tcp-mss "+strconv.Itoa(internetOptions["tcp_mss"].(int)))
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func setSystemLogin(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) error {
@@ -1116,11 +1114,8 @@ func setSystemLogin(d *schema.ResourceData, m interface{}, jnprSess *NetconfObje
}
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func listLinesLogin() []string {
@@ -1201,11 +1196,8 @@ func delSystem(m interface{}, jnprSess *NetconfObject) error {
configSet = append(configSet,
delPrefix+line)
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readSystem(m interface{}, jnprSess *NetconfObject) (systemOptions, error) {
sess := m.(*Session)
diff --git a/junos/resource_system_login_class.go b/junos/resource_system_login_class.go
index 0a2c1441..9111190b 100644
--- a/junos/resource_system_login_class.go
+++ b/junos/resource_system_login_class.go
@@ -54,12 +54,12 @@ func resourceSystemLoginClass() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"access_end": {
Type: schema.TypeString,
Optional: true,
- RequiredWith: []string{"access_end"},
+ RequiredWith: []string{"access_start"},
ValidateFunc: validation.StringMatch(regexp.MustCompile(
`^([0-1]\d|2[0-3]):([0-5]\d):([0-5]\d)$`), "must have HH:MM:SS format"),
},
@@ -185,6 +185,14 @@ func resourceSystemLoginClass() *schema.Resource {
func resourceSystemLoginClassCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSystemLoginClass(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -427,11 +435,7 @@ func setSystemLoginClass(d *schema.ResourceData, m interface{}, jnprSess *Netcon
configSet = append(configSet, setPrefix+"tenant \""+d.Get("tenant").(string)+"\"")
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readSystemLoginClass(class string, m interface{}, jnprSess *NetconfObject) (systemLoginClassOptions, error) {
sess := m.(*Session)
@@ -525,11 +529,8 @@ func delSystemLoginClass(systemLoginClass string, m interface{}, jnprSess *Netco
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete system login class "+systemLoginClass)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillSystemLoginClassData(d *schema.ResourceData, systemLoginClassOptions systemLoginClassOptions) {
if tfErr := d.Set("name", systemLoginClassOptions.name); tfErr != nil {
diff --git a/junos/resource_system_login_user.go b/junos/resource_system_login_user.go
index df918323..86728100 100644
--- a/junos/resource_system_login_user.go
+++ b/junos/resource_system_login_user.go
@@ -35,7 +35,7 @@ func resourceSystemLoginUser() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"class": {
Type: schema.TypeString,
@@ -88,6 +88,14 @@ func resourceSystemLoginUser() *schema.Resource {
func resourceSystemLoginUserCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSystemLoginUser(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -299,11 +307,7 @@ func setSystemLoginUser(d *schema.ResourceData, m interface{}, jnprSess *Netconf
configSet = append(configSet, setPrefix+"full-name \""+d.Get("full_name").(string)+"\"")
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readSystemLoginUser(user string, m interface{}, jnprSess *NetconfObject) (systemLoginUserOptions, error) {
sess := m.(*Session)
@@ -375,11 +379,8 @@ func delSystemLoginUser(systemLoginUser string, m interface{}, jnprSess *Netconf
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete system login user "+systemLoginUser)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillSystemLoginUserData(d *schema.ResourceData, systemLoginUserOptions systemLoginUserOptions) {
if tfErr := d.Set("name", systemLoginUserOptions.name); tfErr != nil {
diff --git a/junos/resource_system_ntp_server.go b/junos/resource_system_ntp_server.go
index 30ce1811..e9993455 100644
--- a/junos/resource_system_ntp_server.go
+++ b/junos/resource_system_ntp_server.go
@@ -47,7 +47,7 @@ func resourceSystemNtpServer() *schema.Resource {
"routing_instance": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"version": {
Type: schema.TypeInt,
@@ -60,6 +60,14 @@ func resourceSystemNtpServer() *schema.Resource {
func resourceSystemNtpServerCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSystemNtpServer(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("address").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -245,11 +253,7 @@ func setSystemNtpServer(d *schema.ResourceData, m interface{}, jnprSess *Netconf
configSet = append(configSet, setPrefix+" version "+strconv.Itoa(d.Get("version").(int)))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readSystemNtpServer(address string, m interface{}, jnprSess *NetconfObject) (ntpServerOptions, error) {
sess := m.(*Session)
@@ -298,11 +302,8 @@ func delSystemNtpServer(address string, m interface{}, jnprSess *NetconfObject)
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete system ntp server "+address)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillSystemNtpServerData(d *schema.ResourceData, ntpServerOptions ntpServerOptions) {
if tfErr := d.Set("address", ntpServerOptions.address); tfErr != nil {
diff --git a/junos/resource_system_radius_server.go b/junos/resource_system_radius_server.go
index fd54bfef..b1e95614 100644
--- a/junos/resource_system_radius_server.go
+++ b/junos/resource_system_radius_server.go
@@ -106,7 +106,7 @@ func resourceSystemRadiusServer() *schema.Resource {
"routing_instance": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"source_address": {
Type: schema.TypeString,
@@ -124,6 +124,14 @@ func resourceSystemRadiusServer() *schema.Resource {
func resourceSystemRadiusServerCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSystemRadiusServer(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("address").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -344,11 +352,7 @@ func setSystemRadiusServer(d *schema.ResourceData, m interface{}, jnprSess *Netc
strconv.Itoa(d.Get("timeout").(int)))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readSystemRadiusServer(address string, m interface{}, jnprSess *NetconfObject) (radiusServerOptions, error) {
sess := m.(*Session)
@@ -456,11 +460,8 @@ func delSystemRadiusServer(address string, m interface{}, jnprSess *NetconfObjec
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete system radius-server "+address)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillSystemRadiusServerData(d *schema.ResourceData, radiusServerOptions radiusServerOptions) {
if tfErr := d.Set("address", radiusServerOptions.address); tfErr != nil {
diff --git a/junos/resource_system_root_authentication.go b/junos/resource_system_root_authentication.go
index 0b830fcf..df88788e 100644
--- a/junos/resource_system_root_authentication.go
+++ b/junos/resource_system_root_authentication.go
@@ -50,6 +50,14 @@ func resourceSystemRootAuthentication() *schema.Resource {
func resourceSystemRootAuthenticationCreate(
ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSystemRootAuthentication(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId("system_root_authentication")
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -178,11 +186,7 @@ func setSystemRootAuthentication(d *schema.ResourceData, m interface{}, jnprSess
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readSystemRootAuthentication(m interface{}, jnprSess *NetconfObject) (systemRootAuthOptions, error) {
sess := m.(*Session)
@@ -230,11 +234,8 @@ func delSystemRootAuthentication(m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete system root-authentication")
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillSystemRootAuthenticationData(d *schema.ResourceData, systemRootAuthOptions systemRootAuthOptions) {
if tfErr := d.Set("encrypted_password", systemRootAuthOptions.encryptedPassword); tfErr != nil {
diff --git a/junos/resource_system_syslog_file.go b/junos/resource_system_syslog_file.go
index 8069f285..c99d6f67 100644
--- a/junos/resource_system_syslog_file.go
+++ b/junos/resource_system_syslog_file.go
@@ -51,7 +51,7 @@ func resourceSystemSyslogFile() *schema.Resource {
Type: schema.TypeString,
Required: true,
ForceNew: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"allow_duplicates": {
Type: schema.TypeBool,
@@ -233,6 +233,14 @@ func resourceSystemSyslogFile() *schema.Resource {
func resourceSystemSyslogFileCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSystemSyslogFile(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("filename").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -520,11 +528,7 @@ func setSystemSyslogFile(d *schema.ResourceData, m interface{}, jnprSess *Netcon
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readSystemSyslogFile(filename string, m interface{}, jnprSess *NetconfObject) (syslogFileOptions, error) {
@@ -677,11 +681,8 @@ func delSystemSyslogFile(filename string, m interface{}, jnprSess *NetconfObject
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete system syslog file "+filename)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillSystemSyslogFileData(d *schema.ResourceData, syslogFileOptions syslogFileOptions) {
diff --git a/junos/resource_system_syslog_host.go b/junos/resource_system_syslog_host.go
index a919cdec..9a8ba4dd 100644
--- a/junos/resource_system_syslog_host.go
+++ b/junos/resource_system_syslog_host.go
@@ -76,7 +76,7 @@ func resourceSystemSyslogHost() *schema.Resource {
"log_prefix": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 32),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 32, FormatDefault),
},
"match": {
Type: schema.TypeString,
@@ -191,6 +191,14 @@ func resourceSystemSyslogHost() *schema.Resource {
func resourceSystemSyslogHostCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setSystemSyslogHost(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("host").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -444,11 +452,7 @@ func setSystemSyslogHost(d *schema.ResourceData, m interface{}, jnprSess *Netcon
configSet = append(configSet, setPrefix+" user "+d.Get("user_severity").(string))
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readSystemSyslogHost(host string, m interface{}, jnprSess *NetconfObject) (syslogHostOptions, error) {
sess := m.(*Session)
@@ -543,11 +547,8 @@ func delSystemSyslogHost(host string, m interface{}, jnprSess *NetconfObject) er
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete system syslog host "+host)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillSystemSyslogHostData(d *schema.ResourceData, syslogHostOptions syslogHostOptions) {
if tfErr := d.Set("host", syslogHostOptions.host); tfErr != nil {
diff --git a/junos/resource_vlan.go b/junos/resource_vlan.go
index afb3ce69..6ac2c365 100644
--- a/junos/resource_vlan.go
+++ b/junos/resource_vlan.go
@@ -41,7 +41,7 @@ func resourceVlan() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"community_vlans": {
Type: schema.TypeList,
@@ -55,17 +55,17 @@ func resourceVlan() *schema.Resource {
"forward_filter_input": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"forward_filter_output": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"forward_flood_input": {
Type: schema.TypeString,
Optional: true,
- ValidateDiagFunc: validateNameObjectJunos([]string{}, 64),
+ ValidateDiagFunc: validateNameObjectJunos([]string{}, 64, FormatDefault),
},
"isolated_vlan": {
Type: schema.TypeInt,
@@ -149,6 +149,14 @@ func resourceVlan() *schema.Resource {
func resourceVlanCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sess := m.(*Session)
+ if sess.junosFakeCreateSetFile != "" {
+ if err := setVlan(d, m, nil); err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(d.Get("name").(string))
+
+ return nil
+ }
jnprSess, err := sess.startNewSession()
if err != nil {
return diag.FromErr(err)
@@ -374,11 +382,7 @@ func setVlan(d *schema.ResourceData, m interface{}, jnprSess *NetconfObject) err
}
}
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
-
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func readVlan(vlan string, m interface{}, jnprSess *NetconfObject) (vlanOptions, error) {
sess := m.(*Session)
@@ -482,11 +486,8 @@ func delVlan(vlan string, m interface{}, jnprSess *NetconfObject) error {
sess := m.(*Session)
configSet := make([]string, 0, 1)
configSet = append(configSet, "delete vlans "+vlan)
- if err := sess.configSet(configSet, jnprSess); err != nil {
- return err
- }
- return nil
+ return sess.configSet(configSet, jnprSess)
}
func fillVlanData(d *schema.ResourceData, vlanOptions vlanOptions) {
diff --git a/junos/session.go b/junos/session.go
index a4261af5..f2728437 100644
--- a/junos/session.go
+++ b/junos/session.go
@@ -2,26 +2,31 @@ package junos
import (
"fmt"
+ "log"
"os"
+ "path"
"strconv"
- "strings"
"time"
)
+const directoryPermission = 0755
+
// Session information to connect on Junos Device.
type Session struct {
- junosPort int
- junosSleepLock int
- junosSleepShort int
- junosSleepSSHClosed int
- junosIP string
- junosUserName string
- junosPassword string
- junosSSHKeyPEM string
- junosSSHKeyFile string
- junosKeyPass string
- junosGroupIntDel string
- junosLogFile string
+ junosPort int
+ junosSleepLock int
+ junosSleepShort int
+ junosSleepSSHClosed int
+ junosFilePermission int64
+ junosIP string
+ junosUserName string
+ junosPassword string
+ junosSSHKeyPEM string
+ junosSSHKeyFile string
+ junosKeyPass string
+ junosGroupIntDel string
+ junosLogFile string
+ junosFakeCreateSetFile string
}
func (sess *Session) startNewSession() (*NetconfObject, error) {
@@ -35,13 +40,6 @@ func (sess *Session) startNewSession() (*NetconfObject, error) {
}
if sess.junosSSHKeyFile != "" {
auth.PrivateKeyFile = sess.junosSSHKeyFile
- if strings.HasPrefix(sess.junosSSHKeyFile, "~") {
- homeDir, err := os.UserHomeDir()
- if err != nil {
- return nil, fmt.Errorf("failed to read user home directory : %w", err)
- }
- auth.PrivateKeyFile = homeDir + sess.junosSSHKeyFile[1:]
- }
if sess.junosKeyPass != "" {
auth.Passphrase = sess.junosKeyPass
}
@@ -56,33 +54,25 @@ func (sess *Session) startNewSession() (*NetconfObject, error) {
if jnpr.SystemInformation.HardwareModel == "" {
return jnpr, fmt.Errorf("can't read model of device with netconf command")
}
- if sess.junosLogFile != "" {
- logFile("[startNewSession] started", sess.junosLogFile)
- }
+ sess.logFile("[startNewSession] started")
return jnpr, nil
}
func (sess *Session) closeSession(jnpr *NetconfObject) {
err := jnpr.Close(sess.junosSleepSSHClosed)
- if sess.junosLogFile != "" {
- if err != nil {
- logFile(fmt.Sprintf("[closeSession] err: %q", err), sess.junosLogFile)
- } else {
- logFile("[closeSession] closed", sess.junosLogFile)
- }
+ if err != nil {
+ sess.logFile(fmt.Sprintf("[closeSession] err: %q", err))
+ } else {
+ sess.logFile("[closeSession] closed")
}
}
func (sess *Session) command(cmd string, jnpr *NetconfObject) (string, error) {
read, err := jnpr.netconfCommand(cmd)
- if sess.junosLogFile != "" {
- logFile(fmt.Sprintf("[command] cmd: %q", cmd), sess.junosLogFile)
- logFile(fmt.Sprintf("[command] read: %q", read), sess.junosLogFile)
- }
+ sess.logFile(fmt.Sprintf("[command] cmd: %q", cmd))
+ sess.logFile(fmt.Sprintf("[command] read: %q", read))
sleepShort(sess.junosSleepShort)
if err != nil && read != emptyWord {
- if sess.junosLogFile != "" {
- logFile(fmt.Sprintf("[command] err: %q", err), sess.junosLogFile)
- }
+ sess.logFile(fmt.Sprintf("[command] err: %q", err))
return "", err
}
@@ -91,15 +81,11 @@ func (sess *Session) command(cmd string, jnpr *NetconfObject) (string, error) {
}
func (sess *Session) commandXML(cmd string, jnpr *NetconfObject) (string, error) {
read, err := jnpr.netconfCommandXML(cmd)
- if sess.junosLogFile != "" {
- logFile(fmt.Sprintf("[commandXML] cmd: %q", cmd), sess.junosLogFile)
- logFile(fmt.Sprintf("[commandXML] read: %q", read), sess.junosLogFile)
- }
+ sess.logFile(fmt.Sprintf("[commandXML] cmd: %q", cmd))
+ sess.logFile(fmt.Sprintf("[commandXML] read: %q", read))
sleepShort(sess.junosSleepShort)
if err != nil {
- if sess.junosLogFile != "" {
- logFile(fmt.Sprintf("[commandXML] err: %q", err), sess.junosLogFile)
- }
+ sess.logFile(fmt.Sprintf("[commandXML] err: %q", err))
return "", err
}
@@ -107,45 +93,60 @@ func (sess *Session) commandXML(cmd string, jnpr *NetconfObject) (string, error)
return read, nil
}
func (sess *Session) configSet(cmd []string, jnpr *NetconfObject) error {
- message, err := jnpr.netconfConfigSet(cmd)
- sleepShort(sess.junosSleepShort)
- if sess.junosLogFile != "" {
- logFile(fmt.Sprintf("[configSet] cmd: %q", cmd), sess.junosLogFile)
- logFile(fmt.Sprintf("[configSet] message: %q", message), sess.junosLogFile)
+ if jnpr != nil {
+ message, err := jnpr.netconfConfigSet(cmd)
+ sleepShort(sess.junosSleepShort)
+ sess.logFile(fmt.Sprintf("[configSet] cmd: %q", cmd))
+ sess.logFile(fmt.Sprintf("[configSet] message: %q", message))
+ if err != nil {
+ sess.logFile(fmt.Sprintf("[configSet] err: %q", err))
+
+ return err
+ }
+
+ return nil
+ } else if sess.junosFakeCreateSetFile != "" {
+ return sess.appendFakeCreateSetFile(cmd)
+ }
+
+ return fmt.Errorf("internal error: sess.configSet call without connection on device")
+}
+
+func (sess *Session) appendFakeCreateSetFile(lines []string) error {
+ dirSetFile := path.Dir(sess.junosFakeCreateSetFile)
+ if _, err := os.Stat(dirSetFile); err != nil {
+ if err := os.MkdirAll(dirSetFile, os.FileMode(directoryPermission)); err != nil {
+ return fmt.Errorf("failed to create parent directory of `%s` : %w", sess.junosFakeCreateSetFile, err)
+ }
}
+ f, err := os.OpenFile(sess.junosFakeCreateSetFile,
+ os.O_APPEND|os.O_CREATE|os.O_WRONLY, os.FileMode(sess.junosFilePermission))
if err != nil {
- if sess.junosLogFile != "" {
- logFile(fmt.Sprintf("[configSet] err: %q", err), sess.junosLogFile)
+ return fmt.Errorf("failed to openfile `%s` : %w", sess.junosFakeCreateSetFile, err)
+ }
+ defer f.Close()
+ for _, v := range lines {
+ if _, err := f.WriteString(v + "\n"); err != nil {
+ return fmt.Errorf("failed to write in file `%s` : %w", sess.junosFakeCreateSetFile, err)
}
-
- return err
}
return nil
}
func (sess *Session) commitConf(logMessage string, jnpr *NetconfObject) (_warnings []error, _err error) {
- if sess.junosLogFile != "" {
- logFile(fmt.Sprintf("[commitConf] commit %q", logMessage), sess.junosLogFile)
- }
+ sess.logFile(fmt.Sprintf("[commitConf] commit %q", logMessage))
warns, err := jnpr.netconfCommit(logMessage)
sleepShort(sess.junosSleepShort)
- if err != nil {
- if sess.junosLogFile != "" {
- logFile(fmt.Sprintf("[commitConf] commit error: %q", err), sess.junosLogFile)
- if len(warns) > 0 {
- for _, w := range warns {
- logFile(fmt.Sprintf("[commitConf] commit warning: %q", w), sess.junosLogFile)
- }
- }
+ if len(warns) > 0 {
+ for _, w := range warns {
+ sess.logFile(fmt.Sprintf("[commitConf] commit warning: %q", w))
}
+ }
+ if err != nil {
+ sess.logFile(fmt.Sprintf("[commitConf] commit error: %q", err))
return warns, err
}
- if len(warns) > 0 && sess.junosLogFile != "" {
- for _, w := range warns {
- logFile(fmt.Sprintf("[commitConf] commit warning: %q", w), sess.junosLogFile)
- }
- }
return warns, nil
}
@@ -155,16 +156,12 @@ func (sess *Session) configLock(jnpr *NetconfObject) {
for {
lock = jnpr.netconfConfigLock()
if lock {
- if sess.junosLogFile != "" {
- logFile("[configLock] locked", sess.junosLogFile)
- }
+ sess.logFile("[configLock] locked")
sleepShort(sess.junosSleepShort)
break
} else {
- if sess.junosLogFile != "" {
- logFile("[configLock] sleep for wait lock", sess.junosLogFile)
- }
+ sess.logFile("[configLock] sleep for wait lock")
sleep(sess.junosSleepLock)
}
}
@@ -172,30 +169,43 @@ func (sess *Session) configLock(jnpr *NetconfObject) {
func (sess *Session) configClear(jnpr *NetconfObject) {
err := jnpr.netconfConfigClear()
sleepShort(sess.junosSleepShort)
- if sess.junosLogFile != "" {
- logFile("[configClear] config clear", sess.junosLogFile)
- }
+ sess.logFile("[configClear] config clear")
if err != nil {
err := jnpr.Close(sess.junosSleepSSHClosed)
- if err != nil && sess.junosLogFile != "" {
- logFile(fmt.Sprintf("[configClear] close err: %q", err), sess.junosLogFile)
+ if err != nil {
+ sess.logFile(fmt.Sprintf("[configClear] close err: %q", err))
}
panic(err)
}
err = jnpr.netconfConfigUnlock()
sleepShort(sess.junosSleepShort)
- if sess.junosLogFile != "" {
- logFile("[configClear] config unlock", sess.junosLogFile)
- }
+ sess.logFile("[configClear] config unlock")
if err != nil {
err := jnpr.Close(sess.junosSleepSSHClosed)
- if err != nil && sess.junosLogFile != "" {
- logFile(fmt.Sprintf("[configClear] close err: %q", err), sess.junosLogFile)
+ if err != nil {
+ sess.logFile(fmt.Sprintf("[configClear] close err: %q", err))
}
panic(err)
}
}
+// log message in junosLogFile.
+func (sess *Session) logFile(message string) {
+ if sess.junosLogFile != "" {
+ f, err := os.OpenFile(sess.junosLogFile,
+ os.O_WRONLY|os.O_CREATE|os.O_APPEND, os.FileMode(sess.junosFilePermission))
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer f.Close()
+
+ log.SetOutput(f)
+ log.SetPrefix(time.Now().Format("2006-01-02 15:04:05"))
+
+ log.Printf("%s", message)
+ }
+}
+
func sleep(timeSleep int) {
time.Sleep(time.Duration(timeSleep) * time.Second)
}
diff --git a/website/docs/d/interface_logical.html.markdown b/website/docs/d/interface_logical.html.markdown
index 0929d1fd..54797c2a 100644
--- a/website/docs/d/interface_logical.html.markdown
+++ b/website/docs/d/interface_logical.html.markdown
@@ -50,6 +50,8 @@ The following arguments are supported:
* `mtu` - Maximum transmission unit.
* `rpf_check` - Reverse-path-forwarding checks enabled and possible configuration. See the [`rpf_check` attributes](#rpf_check-attributes) block for attributes.
* `routing_instance` - Routing_instance where the interface is (if not default instance).
+* `security_inbound_protocols` - The inbound protocols allowed.
+* `security_inbound_services` - The inbound services allowed.
* `security_zone` - Security zone where the interface is.
* `vlan_id` - 802.1q VLAN ID for unit interface.
diff --git a/website/docs/d/interface_physical.html.markdown b/website/docs/d/interface_physical.html.markdown
index b6772c91..4ed6a111 100644
--- a/website/docs/d/interface_physical.html.markdown
+++ b/website/docs/d/interface_physical.html.markdown
@@ -32,12 +32,78 @@ The following arguments are supported:
* `id` - Like resource it's the `name` of interface
* `name` - Name of physical interface (without dot).
-* `ae_lacp` - LACP option in aggregated-ether-options.
-* `ae_link_speed` - Link speed of individual interface that joins the AE.
-* `ae_minimum_links` - Minimum number of aggregated links (1..8).
+* `ae_lacp` (**DEPRECATED**) - LACP option in aggregated-ether-options.
+* `ae_link_speed` (**DEPRECATED**) - Link speed of individual interface that joins the AE.
+* `ae_minimum_links` (**DEPRECATED**) - Minimum number of aggregated links.
* `description` - Description for interface.
-* `ether802_3ad` - Link of 802.3ad interface.
+* `esi` - Define ESI Config parameters. See the [`esi` attributes](#esi-attributes) block.
+* `ether_opts` - Declare 'ether-options' configuration.
+ * `ae_8023ad` - Name of an aggregated Ethernet interface to join.
+ * `auto_negotiation` - Enable auto-negotiation.
+ * `no_auto_negotiation` - Don't enable auto-negotiation.
+ * `flow_control` - Enable flow control.
+ * `no_flow_control` - Don't enable flow control.
+ * `loopback` - Enable loopback.
+ * `no_loopback` - Don't enable loopback.
+ * `redundant_parent` - Name of a redundant ethernet interface to join.
+* `ether802_3ad` (**DEPRECATED**) - Link of 802.3ad interface.
+* `gigether_opts` - Declare 'gigether-options' configuration.
+ * `ae_8023ad` - Name of an aggregated Ethernet interface to join.
+ * `auto_negotiation` - Enable auto-negotiation.
+ * `no_auto_negotiation` - Don't enable auto-negotiation.
+ * `flow_control` - Enable flow control.
+ * `no_flow_control` - Don't enable flow control.
+ * `loopback` - Enable loopback.
+ * `no_loopback` - Don't enable loopback.
+ * `redundant_parent` - Name of a redundant ethernet interface to join.
+* `parent_ether_opts` - Declare 'aggregated-ether-options' or 'redundant-ether-options' configuration (it depends on the interface 'name'). See the [`parent_ether_opts` attributes](#parent_ether_opts-attributes) block.
* `trunk` - Interface mode is trunk.
* `vlan_members` - List of vlan membership for this interface.
* `vlan_native` - Vlan for untagged frames.
* `vlan_tagging` - 802.1q VLAN tagging support.
+
+---
+#### esi attributes
+* `mode` - ESI Mode
+* `identifier` - The ESI value for the interface
+* `auto_derive_lacp` - Auto-derive ESI value for the interface
+* `df_election_type` - DF Election Type
+* `source_bmac` - Unicast Source B-MAC address per ESI for PBB-EVPN
+
+---
+#### parent_ether_opts attributes
+* `bfd_liveness_detection` - Declare 'bfd-liveness-detection' in 'aggregated-ether-options' configuration. See the [`bfd_liveness_detection` attributes in parent_ether_opts](#bfd_liveness_detection-attributes-in-parent_ether_opts) block.
+* `flow_control` - Enable flow control.
+* `no_flow_control` - Don't enable flow control.
+* `lacp` - Declare 'lacp' configuration.
+ * `mode` - Active or passive.
+ * `admin_key` - Node's administrative key.
+ * `periodic` - Timer interval for periodic transmission of LACP packets.
+ * `sync_reset` - On minimum-link failure notify out of sync to peer.
+ * `system_id` - Node's System ID, encoded as a MAC address
+ * `system_priority` - Priority of the system.
+* `loopback` - Enable loopback.
+* `no_loopback` - Don't enable loopback.
+* `link_speed` - Link speed of individual interface that joins the AE.
+* `minimum_bandwidth` - Minimum bandwidth configured for aggregated bundle.
+* `minimum_links` - Minimum number of aggregated/active links.
+* `redundancy_group` - Redundancy group of this interface for reth interface.
+* `source_address_filter` - Source address filters.
+* `source_filtering` - Enable source address filtering.
+
+---
+#### bfd_liveness_detection attributes in parent_ether_opts
+* `local_address` - BFD local address.
+* `authentication_algorithm` - Authentication algorithm name.
+* `authentication_key_chain` - Authentication Key chain name.
+* `authentication_loose_check` - Verify authentication only if authentication is negotiated.
+* `detection_time_threshold` - High detection-time triggering a trap.
+* `holddown_interval` - Time to hold the session-UP notification to the client.
+* `minimum_interval` - Minimum transmit and receive interval.
+* `minimum_receive_interval` - Minimum receive interval.
+* `multiplier` - Detection time multiplier.
+* `neighbor` - BFD neighbor address.
+* `no_adaptation` - Disable adaptation.
+* `transmit_interval_minimum_interval` - Minimum transmit interval
+* `transmit_interval_threshold` - High transmit interval triggering a trap.
+* `version` - BFD protocol version number.
\ No newline at end of file
diff --git a/website/docs/index.html.markdown b/website/docs/index.html.markdown
index bb0cc44b..231f8237 100644
--- a/website/docs/index.html.markdown
+++ b/website/docs/index.html.markdown
@@ -124,10 +124,26 @@ The following arguments are supported in the `provider` block:
Defaults to `0`.
---
-#### Debug options
+#### Debug & workaround options
+* `file_permission` - (Optional) The permission to set for the created file (debug, setfile).
+ Defaults to `0644`.
+ It can also be sourced from the `JUNOS_FILE_PERMISSION` environment variable.
+
* `debug_netconf_log_path` - (Optional) more detailed log (netconf) in the specified file.
It can also be sourced from the `JUNOS_LOG_PATH` environment variable.
+* `fake_create_with_setfile` - (Optional, **don't use in normal terraform run**) When this option is set (with a path to a file), the normal process to create resources (netconf connection, precheck, generate/upload set lines in candidate configuration, commit, postcheck) skipped to generate set lines, append them to the specified file, and respond with a `fake` successful creation of resource to Terraform.
+Then you can upload/commit the file with the `junos_null_commit_file` resource in the same config or another terraform config or with another way.
+If you are using `junos_null_commit_file` in the same terraform config, you must create dependencies between resources so that the creation of the ` junos_null_commit_file` resource is alone and last.
+This options is useful to create a workaround for a long terraform run if there are many ressources to be created and Junos device is slow to commit.
+As many tests are skipped, this option may generate extra config (not managed by terraform) on Junos device or conficts/errors for resources in tfstate. A `terraform refresh` will be able to detect parts of errors but **be carefully with this option**.
+There are exceptions for ressources :
+ * `junos_null_commit_file` - Of course, the skip doesn’t concern this resource.
+ * `junos_interface_st0_unit` cannot take into account the option and run still normal process.
+ * `junos_interface_physical` don’t generate `chassis aggregated-devices ethernet device-count` line when it should be necessary.
+
+ It can also be sourced from the `JUNOS_FAKECREATE_SETFILE` environment variable.
+
## Interface specifications
When create a resource for a physical interface, the provider considers the interface available if there is 'apply-groups [`group_interface_delete`](#group_interface_delete)' and only this line on interface configuration.
diff --git a/website/docs/r/bgp_group.html.markdown b/website/docs/r/bgp_group.html.markdown
index 81c98331..e9bcd937 100644
--- a/website/docs/r/bgp_group.html.markdown
+++ b/website/docs/r/bgp_group.html.markdown
@@ -41,8 +41,16 @@ The following arguments are supported:
**WARNING** Clear in tfstate.
* `authentication_key_chain` - (Optional)(`String`) Key chain name. Conflict with `authentication_key`.
* `bfd_liveness_detection` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Define Bidirectional Forwarding Detection (BFD) options. See the [`bfd_liveness_detection` arguments](#bfd_liveness_detection-arguments) block. Max of 1.
+* `bgp_multipath` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to allow load sharing among multiple BGP paths.
+ * `allow_protection` - (Optional)(`Bool`) Allows the BGP multipath and protection to co-exist.
+ * `disable` - (Optional)(`Bool`) Disable Multipath.
+ * `multiple_as` - (Optional)(`Bool`) Use paths received from different ASs.
+* `cluster` - (Optional)(`String`) Cluster identifier. Must be a valid IP address.
* `damping` - (Optional)(`Bool`) Enable route flap damping.
* `export` - (Optional)(`ListOfString`) Export policy list.
+* `family_evpn` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for the `signaling` nlri_type.
+ * `nlri_type` - (Optional)(`String`) NLRI type. Need to be `signaling`. Default to `signaling`.
+ * other options same as [`family_inet` arguments](#family_inet-arguments).
* `family_inet` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified multiple times for each nlri_type.
See the [`family_inet` arguments](#family_inet-arguments) block.
* `family_inet6` Same options as [`family_inet` arguments](#family_inet-arguments) but for inet6 family.
@@ -66,7 +74,8 @@ See the [`family_inet` arguments](#family_inet-arguments) block.
* `metric_out_minimum_igp_offset` - (Optional)(`Bool`) Metric offset for MED. Conflict with `metric_out` and `metric_out_(?!minimum)_*`.
* `mtu_discovery` - (Optional)(`Bool`) Enable TCP path MTU discovery.
* `multihop` - (Optional)(`Bool`) Configure an EBGP multihop session.
-* `multipath` - (Optional)(`Bool`) Allow load sharing among multiple BGP paths.
+* `multipath` - (Optional,**DEPRECATED**)(`Bool`) Allow load sharing among multiple BGP paths.
+Deprecated argument, use the `bgp_multipath` argument instead.
* `out_delay` - (Optional)(`Int`) How long before exporting routes from routing table.
* `passive` - (Optional)(`Bool`) Do not send open messages to a peer.
* `peer_as` - (Optional)(`String`) Autonomous system number.
@@ -90,7 +99,7 @@ See the [`family_inet` arguments](#family_inet-arguments) block.
---
#### family_inet arguments
-Also for `family_inet6`
+Also for `family_inet6` and `family_evpn` (except `nlri_type`)
* `nlri_type` - (Required)(`String`) NLRI type. Need to be 'any', 'flow', 'labeled-unicast', 'unicast' or 'multicast'.
* `accepted_prefix_limit` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for define maximum number of prefixes accepted from a peer and options.
diff --git a/website/docs/r/bgp_neighbor.html.markdown b/website/docs/r/bgp_neighbor.html.markdown
index f6a3b9fc..591a39db 100644
--- a/website/docs/r/bgp_neighbor.html.markdown
+++ b/website/docs/r/bgp_neighbor.html.markdown
@@ -42,8 +42,16 @@ The following arguments are supported:
**WARNING** Clear in tfstate.
* `authentication_key_chain` - (Optional)(`String`) Key chain name. Conflict with `authentication_key`.
* `bfd_liveness_detection` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Define Bidirectional Forwarding Detection (BFD) options. See the [`bfd_liveness_detection` arguments](#bfd_liveness_detection-arguments) block. Max of 1.
+* `bgp_multipath` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to allow load sharing among multiple BGP paths.
+ * `allow_protection` - (Optional)(`Bool`) Allows the BGP multipath and protection to co-exist.
+ * `disable` - (Optional)(`Bool`) Disable Multipath.
+ * `multiple_as` - (Optional)(`Bool`) Use paths received from different ASs.
+* `cluster` - (Optional)(`String`) Cluster identifier. Must be a valid IP address.
* `damping` - (Optional)(`Bool`) Enable route flap damping.
* `export` - (Optional)(`ListOfString`) Export policy list.
+* `family_evpn` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for the `signaling` nlri_type.
+ * `nlri_type` - (Optional)(`String`) NLRI type. Need to be `signaling`. Default to `signaling`.
+ * other options same as [`family_inet` arguments](#family_inet-arguments).
* `family_inet` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified multiple times for each nlri_type.
See the [`family_inet` arguments](#family_inet-arguments) block.
* `family_inet6` Same options as [`family_inet` arguments](#family_inet-arguments) but for inet6 family.
@@ -67,7 +75,8 @@ See the [`family_inet` arguments](#family_inet-arguments) block.
* `metric_out_minimum_igp_offset` - (Optional)(`Bool`) Metric offset for MED. Conflict with `metric_out` and `metric_out_(?!minimum)_*`.
* `mtu_discovery` - (Optional)(`Bool`) Enable TCP path MTU discovery.
* `multihop` - (Optional)(`Bool`) Configure an EBGP multihop session.
-* `multipath` - (Optional)(`Bool`) Allow load sharing among multiple BGP paths.
+* `multipath` - (Optional,**DEPRECATED**)(`Bool`) Allow load sharing among multiple BGP paths.
+Deprecated argument, use the `bgp_multipath` argument instead.
* `out_delay` - (Optional)(`Int`) How long before exporting routes from routing table.
* `passive` - (Optional)(`Bool`) Do not send open messages to a peer.
* `peer_as` - (Optional)(`String`) Autonomous system number.
@@ -91,7 +100,7 @@ See the [`family_inet` arguments](#family_inet-arguments) block.
---
#### family_inet arguments
-Also for `family_inet6`
+Also for `family_inet6` and `family_evpn` (except `nlri_type`)
* `nlri_type` - (Required)(`String`) NLRI type. Need to be 'any', 'flow', 'labeled-unicast', 'unicast' or 'multicast'.
* `accepted_prefix_limit` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for define maximum number of prefixes accepted from a peer and options.
diff --git a/website/docs/r/chassis_cluster.html.markdown b/website/docs/r/chassis_cluster.html.markdown
new file mode 100644
index 00000000..681c2455
--- /dev/null
+++ b/website/docs/r/chassis_cluster.html.markdown
@@ -0,0 +1,77 @@
+---
+layout: "junos"
+page_title: "Junos: junos_chassis_cluster"
+sidebar_current: "docs-junos-resource-chassis-cluster"
+description: |-
+ Configure chassis cluster configuration (when Junos device supports it)
+---
+
+# junos_chassis_cluster
+
+-> **Note:** This resource should only be created **once**. It's used to configure static (not object) options in `chassis cluster` block and `interfaces fab0/1`.
+
+Configure static configuration in `chassis cluster` block and `interfaces fab0/1`.
+
+## Example Usage
+
+```hcl
+# Configure chassis cluster
+resource "junos_chassis_cluster" "cluster" {
+ fab0 {
+ member_interfaces = ["ge-0/0/3"]
+ }
+ redundancy_group { # id 0
+ node0_priority = 100
+ node1_priority = 50
+ }
+ redundancy_group { # id 1
+ node0_priority = 100
+ node1_priority = 50
+ interface_monitor {
+ name = "ge-0/0/4"
+ weight = 255
+ }
+ interface_monitor {
+ name = "ge-0/0/5"
+ weight = 254
+ }
+ }
+ reth_count = 2
+}
+```
+
+## Argument Reference
+
+The following arguments are supported:
+
+* `fab0` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'interfaces fab0' configuration.
+ * `member_interfaces` - (Optional)(`ListOfString`) Member interfaces for the fabric interface.
+ * `description` - (Optional)(`String`) Text description of interface.
+* `fab1` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'interfaces fab1' configuration.
+ * `member_interfaces` - (Optional)(`ListOfString`) Member interfaces for the fabric interface.
+ * `description` - (Optional)(`String`) Text description of interface.
+* `redundancy_group` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified multiple times for each redundancy-group to declare. First in list have id=0, second id=1, etc.
+ * `node0_priority` - (Required)(`Int`) Priority of the node in the redundancy-group (1..254).
+ * `node1_priority` - (Required)(`Int`) Priority of the node in the redundancy-group (1..254).
+ * `gratuitous_arp_count` - (Optional)(`Int`) Number of gratuitous ARPs to send on an active interface after failover (1..16).
+ * `hold_down_interval` - (Optional)(`Int`) RG failover interval. RG0(300-1800) RG1+(0-1800) (0..1800 seconds)
+ * `interface_monitor` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified multiple times for each monitoring interface to declare. See the [`interface_monitor` arguments for redundancy_group] (#interface_monitor-arguments-for-redundancy_group) block.
+ * `preempt` - (Optional)(`Bool`) Allow preemption of primaryship based on priority.
+* `reth_count` - (Required)(`Int`) Number of redundant ethernet interfaces (1..128)
+* `config_sync_no_secondary_bootup_auto` - (Optional)(`Bool`) Disable auto configuration synchronize on secondary bootup.
+* `control_link_recovery` - (Optional)(`Bool`) Enable automatic control link recovery.
+* `heartbeat_interval` - (Optional)(`Int`) Interval between successive heartbeats (1000..2000 milliseconds).
+* `heartbeat_threshold` - (Optional)(`Int`) Number of consecutive missed heartbeats to indicate device failure (3..8).
+
+---
+#### interface_monitor arguments for redundancy_group
+* `name` - (Required)(`String`) Name of the interface to monitor.
+* `weight` - (Required)(`Int`) Weight assigned to this interface that influences failover (0..255).
+
+## Import
+
+Junos chassis cluster can be imported using any id, e.g.
+
+```
+$ terraform import junos_chassis_cluster.cluster random
+```
diff --git a/website/docs/r/group_dual_system.html.markdown b/website/docs/r/group_dual_system.html.markdown
new file mode 100644
index 00000000..36181413
--- /dev/null
+++ b/website/docs/r/group_dual_system.html.markdown
@@ -0,0 +1,78 @@
+---
+layout: "junos"
+page_title: "Junos: junos_group_dual_system"
+sidebar_current: "docs-junos-group-dual-system"
+description: |-
+ Create a group for member of dual system (node/re)
+---
+
+# junos_group_dual_system
+
+Provides a group resource for member of dual system (node/re).
+
+## Example Usage
+
+```hcl
+# Configure a group for member of dual system.
+resource "junos_group_dual_system" "node0" {
+ name = "node0"
+ interface_fxp0 {
+ description = "demo"
+ family_inet_address {
+ cidr_ip = "192.0.2.193/26"
+ }
+ family_inet_address {
+ cidr_ip = "192.0.2.194/26"
+ master_only = true
+ }
+ }
+ routing_options {
+ static_route {
+ destination = "192.0.2.0/26"
+ next_hop = ["192.0.2.254"]
+ }
+ }
+ system {
+ host_name = "test_node"
+ backup_router_address = "192.0.2.254"
+ backup_router_destination = ["192.0.2.0/26"]
+ }
+}
+```
+
+## Argument Reference
+
+The following arguments are supported:
+
+* `name` - (Required, Forces new resource)(`String`) Name of group.
+* `apply_groups` - (Optional)(`Bool`) Apply the group. Defaults to `true`.
+* `interface_fxp0` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for configure `fxp0` interface. See the [`interface_fxp0` arguments] (#interface_fxp0-arguments) block.
+* `routing_options` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for configure `routing-options` block. See the [`routing_options` arguments] (#routing_options-arguments) block.
+* `security` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for configure `security` block.
+ * `log_source_address` - (Required)(`String`) Source ip address used when exporting security logs.
+* `system` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html))
+Can be specified only once for configure `system` block.
+ * `host_name` - (Optional)(`String`) Hostname.
+ * `backup_router_address` - (Optional)(`String`) IPv4 address backup router.
+ * `backup_router_destination` - (Optional)(`ListOfString`) Destinations network reachable through the router.
+
+---
+#### interface_fxp0 arguments
+* `description` - (Optional)(`String`) Description for interface.
+* `family_inet_address` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified multiple times for each ip address to declare.
+ * `cidr_ip` - (Required)(`String`) Address IP/Mask v4.
+ * `master_only` - (Optional)(`Bool`) Master management IP address.
+
+---
+#### routing_options arguments
+* `static_route` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified multiple times for each destination to declare.
+ * `destination` - (Required)(`String`) The destination for static route.
+ * `next_hop` - (Required)(`ListOfString`) List of next-hop.
+
+## Import
+
+Junos group can be imported using an id made up of ``, e.g.
+
+```
+$ terraform import junos_group_dual_system.node0 node0
+```
diff --git a/website/docs/r/interface_logical.html.markdown b/website/docs/r/interface_logical.html.markdown
index a2d0b6d2..a2750461 100644
--- a/website/docs/r/interface_logical.html.markdown
+++ b/website/docs/r/interface_logical.html.markdown
@@ -45,6 +45,8 @@ The following arguments are supported:
* `mtu` - (Optional)(`Int`) Maximum transmission unit.
* `rpf_check` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for enable reverse-path-forwarding checks on this interface. See the [`rpf_check` arguments](#rpf_check-arguments) block for optional arguments.
* `routing_instance` - (Optional)(`String`) Add this interface in routing_instance. Need to be created before.
+* `security_inbound_protocols` - (Optional)(`ListOfString`) The inbound protocols allowed. Must be a list of Junos protocols. `security_zone` need to be set.
+* `security_inbound_services` - (Optional)(`ListOfString`) The inbound services allowed. Must be a list of Junos services. `security_zone` need to be set.
* `security_zone` - (Optional)(`String`) Add this interface in security_zone. Need to be created before.
* `vlan_id` - (Optional,Computed)(`Int`) 802.1q VLAN ID for unit interface. If not set, computed with `name` of interface (ge-0/0/0.100 = 100) except if name has '.0' suffix or 'st0.' prefix.
diff --git a/website/docs/r/interface_physical.html.markdown b/website/docs/r/interface_physical.html.markdown
index 4ac172ff..df91bf91 100644
--- a/website/docs/r/interface_physical.html.markdown
+++ b/website/docs/r/interface_physical.html.markdown
@@ -30,21 +30,91 @@ resource junos_interface_physical "interface_fw_demo" {
## Argument Reference
+~> **NOTE:** This resource computes the maximum number of aggregate interfaces required with the current configuration (searches lines `ether-options 802.3ad` and `ae` interfaces set) then add/remove `chassis aggregated-devices ethernet device-count` line with this maximum.
+
The following arguments are supported:
* `name` - (Required, Forces new resource)(`String`) Name of physical interface (without dot).
* `no_disable_on_destroy` - (Optional)(`Bool`) When destroy this resource, delete all configurations => do not add `disable` + `descrition NC` or `apply-groups` with `group_interface_delete` provider argument on interface.
-* `ae_lacp` - (Optional)(`String`) Add lacp option in aggregated-ether-options. Need to be 'active' or 'passive' for initiate transmission or respond.
-* `ae_link_speed` - (Optional)(`String`) Link speed of individual interface that joins the AE.
-* `ae_minimum_links` - (Optional)(`Int`) Minimum number of aggregated links (1..8).
+* `ae_lacp` - (Optional,**DEPRECATED**)(`String`) Add lacp option in aggregated-ether-options. Need to be 'active' or 'passive' for initiate transmission or respond.
+Deprecated argument, use the `parent_ether_opts` argument instead.
+* `ae_link_speed` - (Optional,**DEPRECATED**)(`String`) Link speed of individual interface that joins the AE.
+Deprecated argument, use the `parent_ether_opts` argument instead.
+* `ae_minimum_links` - (Optional,**DEPRECATED**)(`Int`) Minimum number of aggregated links.
+Deprecated argument, use the `parent_ether_opts` argument instead.
* `description` - (Optional)(`String`) Description for interface.
-* `ether802_3ad` - (Optional)(`String`) Name of aggregated device for add this interface to link of 802.3ad interface.
+* `esi` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to define ESI Config parameters. See the [`esi` arguments](#esi-arguments) block.
+* `ether_opts` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'ether-options' configuration. Conflict with 'gigether_opts'.
+ * `ae_8023ad` - (Optional)(`String`) Name of an aggregated Ethernet interface to join.
+ * `auto_negotiation` - (Optional)(`Bool`) Enable auto-negotiation.
+ * `no_auto_negotiation` - (Optional)(`Bool`) Don't enable auto-negotiation.
+ * `flow_control` - (Optional)(`Bool`) Enable flow control.
+ * `no_flow_control` - (Optional)(`Bool`) Don't enable flow control.
+ * `loopback` - (Optional)(`Bool`) Enable loopback.
+ * `no_loopback` - (Optional)(`Bool`) Don't enable loopback.
+ * `redundant_parent` - (Optional)(`String`) Name of a redundant ethernet interface to join.
+* `ether802_3ad` - (Optional,**DEPRECATED**)(`String`) Name of aggregated device for add this interface to link of 802.3ad interface.
+Deprecated argument, use the `ether_opts` or `gigether_opts` argument instead.
+* `gigether_opts` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'gigether-options' configuration. Conflict with 'ether_opts'.
+ * `ae_8023ad` - (Optional)(`String`) Name of an aggregated Ethernet interface to join.
+ * `auto_negotiation` - (Optional)(`Bool`) Enable auto-negotiation.
+ * `no_auto_negotiation` - (Optional)(`Bool`) Don't enable auto-negotiation.
+ * `flow_control` - (Optional)(`Bool`) Enable flow control.
+ * `no_flow_control` - (Optional)(`Bool`) Don't enable flow control.
+ * `loopback` - (Optional)(`Bool`) Enable loopback.
+ * `no_loopback` - (Optional)(`Bool`) Don't enable loopback.
+ * `redundant_parent` - (Optional)(`String`) Name of a redundant ethernet interface to join.
+* `parent_ether_opts` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'aggregated-ether-options' or 'redundant-ether-options' configuration (it depends on the interface 'name'). See the [`parent_ether_opts` arguments](#parent_ether_opts-arguments) block.
* `trunk` - (Optional)(`Bool`) Interface mode is trunk.
* `vlan_members` - (Optional)(`ListOfString`) List of vlan for membership for this interface.
* `vlan_native` - (Optional)(`Int`) Vlan for untagged frames.
* `vlan_tagging` - (Optional)(`Bool`) Add 802.1q VLAN tagging support.
-~> **NOTE:** This resource computes the maximum number of aggregate interfaces required with the current configuration (searches lines `ether-options 802.3ad` and `ae` interfaces set) then add/remove `chassis aggregated-devices ethernet device-count` line with this maximum.
+---
+#### esi arguments
+* `mode` - (Required)(`String`) ESI Mode
+* `identifier` - (Optional)(`String`) The ESI value for the interface
+* `auto_derive_lacp` - (Optional)(`Bool`) Auto-derive ESI value for the interface
+* `df_election_type` - (Optional)(`String`) DF Election Type
+* `source_bmac` - (Optional)(`String`) Unicast Source B-MAC address per ESI for PBB-EVPN
+
+---
+#### parent_ether_opts arguments
+* `bfd_liveness_detection` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'bfd-liveness-detection' in 'aggregated-ether-options' configuration. See the [`bfd_liveness_detection` arguments in parent_ether_opts](#bfd_liveness_detection-arguments-in-parent_ether_opts) block.
+* `flow_control` - (Optional)(`Bool`) Enable flow control.
+* `no_flow_control` - (Optional)(`Bool`) Don't enable flow control.
+* `lacp` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'lacp' configuration.
+ * `mode` - (Required)(`String`) Active or passive.
+ * `admin_key` - (Optional)(`Int`) Node's administrative key.
+ * `periodic` - (Optional)(`String`) Timer interval for periodic transmission of LACP packets. Need to be 'fast' or 'slow'.
+ * `sync_reset` - (Optional)(`String`) On minimum-link failure notify out of sync to peer. Need to be 'disable' or 'enable'.
+ * `system_id` - (Optional)(`String`) Node's System ID, encoded as a MAC address
+ * `system_priority` - (Optional)(`Int`) Priority of the system (0 ... 65535).
+* `loopback` - (Optional)(`Bool`) Enable loopback.
+* `no_loopback` - (Optional)(`Bool`) Don't enable loopback.
+* `link_speed` - (Optional)(`String`) Link speed of individual interface that joins the AE.
+* `minimum_bandwidth` - (Optional)(`String`) Minimum bandwidth configured for aggregated bundle. Need to be 'N (k|g|m)?bps' format.
+* `minimum_links` - (Optional)(`Int`) Minimum number of aggregated/active links (1..64).
+* `redundancy_group` - (Optional)(`Int`) Redundancy group of this interface (1..128) for reth interface.
+* `source_address_filter` - (Optional)(`ListOfString`) Source address filters.
+* `source_filtering` - (Optional)(`Bool`) Enable source address filtering.
+
+---
+#### bfd_liveness_detection arguments in parent_ether_opts
+* `local_address` - (Required)(`String`) BFD local address.
+* `authentication_algorithm` - (Optional)(`String`) Authentication algorithm name.
+* `authentication_key_chain` - (Optional)(`String`) Authentication Key chain name.
+* `authentication_loose_check` - (Optional)(`Bool`) Verify authentication only if authentication is negotiated.
+* `detection_time_threshold` - (Optional)(`Int`) High detection-time triggering a trap (milliseconds).
+* `holddown_interval` - (Optional)(`Int`) Time to hold the session-UP notification to the client (0..255000 milliseconds).
+* `minimum_interval` - (Optional)(`Int`) Minimum transmit and receive interval (1..255000 milliseconds).
+* `minimum_receive_interval` - (Optional)(`Int`) Minimum receive interval (1..255000 milliseconds).
+* `multiplier` - (Optional)(`Int`) Detection time multiplier (1..255).
+* `neighbor` - (Optional)(`String`) BFD neighbor address.
+* `no_adaptation` - (Optional)(`Bool`) Disable adaptation.
+* `transmit_interval_minimum_interval` - (Optional)(`Int`) Minimum transmit interval (1..255000 milliseconds).
+* `transmit_interval_threshold` - (Optional)(`Int`) High transmit interval triggering a trap (milliseconds).
+* `version` - (Optional)(`String`) BFD protocol version number.
## Import
diff --git a/website/docs/r/null_commit_file.html.markdown b/website/docs/r/null_commit_file.html.markdown
new file mode 100644
index 00000000..4225ac5a
--- /dev/null
+++ b/website/docs/r/null_commit_file.html.markdown
@@ -0,0 +1,36 @@
+---
+layout: "junos"
+page_title: "Junos: junos_null_commit_file"
+sidebar_current: "docs-junos-resource-null-commmit-file"
+description: |-
+ Load a file with set/delete lines on device and commit
+---
+
+# junos_null_commit_file
+
+Load a file with set/delete lines on device and commit
+
+~> **NOTE:** Not provide a real resource, just load content of file with set/delete to candidate configuration on device, and commit
+
+## Example Usage
+
+```hcl
+# Load file and commit
+variable "setfile" { default = "~/junos/setfile" }
+resource junos_null_commit_file "setfile" {
+ filename = var.setfile
+ triggers = {
+ md5 = filemd5(var.setfile)
+ }
+ # clear_file_after_commit = true
+}
+```
+
+## Argument Reference
+
+The following arguments are supported:
+
+* `filename` - (Required, Forces new resource)(`String`) The path of the file to load
+* `append_lines` - (Optional, Forces new resource)(`ListOfString`) List of lines append to lines in the loaded file.
+* `clear_file_after_commit` - (Optional, Forces new resource)(`Bool`) Truncate file after successful commit.
+* `triggers` - (Optional, Forces new resource)(`Map`) A map of arbitrary strings that, when changed, will force the resource to be replaced.
diff --git a/website/docs/r/policyoptions_policy_statement.html.markdown b/website/docs/r/policyoptions_policy_statement.html.markdown
index de057ec7..49adb772 100644
--- a/website/docs/r/policyoptions_policy_statement.html.markdown
+++ b/website/docs/r/policyoptions_policy_statement.html.markdown
@@ -106,16 +106,16 @@ The following arguments are supported:
* `value` - (Required)(`String`) Value for action
* `default_action` - (Optional)(`String`) Set default policy action. Can be 'accept' or 'reject'.
* `load_balance` - (Optional)(`String`) Type of load balancing in forwarding table. Can be 'per-packet' or 'consistent-hash'.
-* `local_preference` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare local-preference action.
+* `local_preference` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare local-preference action.
* `action` - (Required)(`String`) Action on local-preference. Need to be 'add', 'subtract' or 'none'.
* `value` - (Required)(`String`) Value for action
* `next` - (Optional)(`String`) Skip to next 'policy' or 'term'.
* `next_hop` - (Optional)(`String`) Set the address of the next-hop router
-* `metric` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare metric action.
+* `metric` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare metric action.
* `action` - (Required)(`String`) Action on metric. Need to be 'add', 'subtract' or 'none'.
* `value` - (Required)(`String`) Value for action
* `origin` - (Optional)(`String`) BGP path origin
-* `preference` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare preference action.
+* `preference` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare preference action.
* `action` - (Required)(`String`) Action on preference. Need to be 'add', 'subtract' or 'none'.
* `value` - (Required)(`String`) Value for action
diff --git a/website/docs/r/routing_options.html.markdown b/website/docs/r/routing_options.html.markdown
index f99102d6..f48b8350 100644
--- a/website/docs/r/routing_options.html.markdown
+++ b/website/docs/r/routing_options.html.markdown
@@ -28,11 +28,11 @@ resource junos_routing_options "routing_options" {
The following arguments are supported:
-* `autonomous_system` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'autonomous-system' configuration.
+* `autonomous_system` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'autonomous-system' configuration.
* `number` - (Required)(`String`) Autonomous system number in plain number or 'higher 16bits'.'Lower 16 bits' (asdot notation) format.
* `asdot_notation` - (Optional)(`Bool`) Use AS-Dot notation to display true 4 byte AS numbers.
* `loops` - (Optional)(`Int`) Maximum number of times this AS can be in an AS path (1..10).
-* `graceful_restart` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'graceful-restart' configuration.
+* `graceful_restart` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'graceful-restart' configuration.
* `disable` - (Optional)(`Bool`) Disable graceful restart.
* `restart_duration` - (Optional)(`Int`) Maximum time for which router is in graceful restart (120..10000).
diff --git a/website/docs/r/security.html.markdown b/website/docs/r/security.html.markdown
index da0f1c37..bc540bf8 100644
--- a/website/docs/r/security.html.markdown
+++ b/website/docs/r/security.html.markdown
@@ -30,16 +30,17 @@ resource junos_security "security" {
The following arguments are supported:
-* `alg` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'alg' configuration. See the [`alg` arguments] (#alg-arguments) block.
-* `flow` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'flow' configuration. See the [`flow` arguments] (#flow-arguments) block.
-* `forwarding_options` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'forwarding-options' configuration. See the [`forwarding_options` arguments] (#forwarding_options-arguments) block.
-* `ike_traceoptions` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'ike traceoptions' configuration.
- * `file` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'file' configuration. See the [`file` arguments for ike_traceoptions] (#file-arguments-for-ike_traceoptions) block.
+* `alg` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'alg' configuration. See the [`alg` arguments] (#alg-arguments) block.
+* `flow` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'flow' configuration. See the [`flow` arguments] (#flow-arguments) block.
+* `forwarding_options` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'forwarding-options' configuration. See the [`forwarding_options` arguments] (#forwarding_options-arguments) block.
+* `ike_traceoptions` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'ike traceoptions' configuration.
+ * `file` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'file' configuration. See the [`file` arguments for ike_traceoptions] (#file-arguments-for-ike_traceoptions) block.
* `flag` - (Optional)(`ListOfString`) Tracing parameters for IKE.
* `rate_limit` - (Optional)(`Int`) Limit the incoming rate of trace messages (0..4294967295)
-* `log` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'log' configuration. See the [`log` arguments] (#log-arguments) block.
-* `utm` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'utm' configuration.
+* `log` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'log' configuration. See the [`log` arguments] (#log-arguments) block.
+* `utm` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'utm' configuration.
* `feature_profile_web_filtering_type` - (Optional)(`String`) Configuring feature-profile web-filtering type. Need to be 'juniper-enhanced', 'juniper-local', 'web-filtering-none' or 'websense-redirect'.
+ * `feature_profile_web_filtering_juniper_enhanced_server` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'server' configuration. See the [`feature_profile_web_filtering_juniper_enhanced_server` arguments for utm] (#feature_profile_web_filtering_juniper_enhanced_server-arguments-for-utm) block.
---
#### alg arguments
@@ -67,11 +68,11 @@ The following arguments are supported:
---
#### flow arguments
-* `advanced_options` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'flow advanced-options' configuration.
+* `advanced_options` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'flow advanced-options' configuration.
* `drop_matching_reserved_ip_address` - (Optional)(`Bool`) Drop matching reserved source IP address.
* `drop_matching_link_local_address` - (Optional)(`Bool`) Drop matching link local address.
* `reverse_route_packet_mode_vr` - (Optional)(`Bool`) Allow reverse route lookup with packet mode vr.
-* `aging` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'flow aging' configuration.
+* `aging` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'flow aging' configuration.
* `early_ageout` - (Optional)(`Int`) Delay before device declares session invalid (1..65535 seconds).
* `high_watermark` - (Optional)(`Bool`) Percentage of session-table capacity at which aggressive aging-out starts (0..100 percent).
* `low_watermark` - (Optional)(`Bool`) Percentage of session-table capacity at which aggressive aging-out ends (0..100 percent).
@@ -79,7 +80,7 @@ The following arguments are supported:
* `allow_embedded_icmp` - (Optional)(`Bool`) Allow embedded ICMP packets not matching a session to pass through.
* `allow_reverse_ecmp` - (Optional)(`Bool`) Allow reverse ECMP route lookup.
* `enable_reroute_uniform_link_check_nat` - (Optional)(`Bool`) Enable reroute check with uniform link and NAT check.
-* `ethernet_switching` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'flow ethernet-switching' configuration.
+* `ethernet_switching` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'flow ethernet-switching' configuration.
* `block_non_ip_all` - (Optional)(`Bool`) Block all non-IP and non-ARP traffic including broadcast/multicast.
* `bypass_non_ip_unicast` - (Optional)(`Bool`) Allow all non-IP (including unicast) traffic.
* `bpdu_vlan_flooding` - (Optional)(`Bool`) Set 802.1D BPDU flooding based on VLAN.
@@ -93,7 +94,7 @@ The following arguments are supported:
* `route_change_timeout` - (Optional)(`Int`) Timeout value for route change to nonexistent route (6..1800 seconds).
* `syn_flood_protection_mode` - (Optional)(`String`) TCP SYN flood protection mode. Need to be 'syn-cookie' or 'syn-proxy'.
* `sync_icmp_session` - (Optional)(`Bool`) Allow icmp sessions to sync to peer node.
-* `tcp_mss` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'flow tcp-mss' configuration.
+* `tcp_mss` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'flow tcp-mss' configuration.
* `all_tcp_mss` - (Optional)(`Int`) Enable MSS override for all packets with this value.
* `gre_in` - Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for enable MSS override for all GRE packets coming out of an IPSec tunnel.
There is one argument : `mss` - (Optional)(`Int`) MSS Value.
@@ -101,7 +102,7 @@ The following arguments are supported:
There is one argument : `mss` - (Optional)(`Int`) MSS Value.
* `ipsec_vpn` - Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for enable MSS override for all packets entering IPSec tunnel.
There is one argument : `mss` - (Optional)(`Int`) MSS Value.
-* `tcp_session` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'flow tcp-session' configuration.
+* `tcp_session` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'flow tcp-session' configuration.
* `fin_invalidate_session` - (Optional)(`Bool`) Immediately end session on receipt of fin (FIN) segment.
* `maximum_window` - Maximum TCP proxy scaled receive window. Need to be '64K', '128K', '256K', '512K' or '1M'.
* `no_sequence_check` - (Optional)(`Bool`) Disable sequence-number checking.
@@ -111,7 +112,7 @@ The following arguments are supported:
* `rst_sequence_check` - (Optional)(`Bool`) Check sequence number in reset (RST) segment.
* `strict_syn_check` - (Optional)(`Bool`) Enable strict syn check. Conflict with `no_sync_check` and `no_syn_check_in_tunnel`.
* `tcp_initial_timeout` - (Optional)(`Int`) Timeout for TCP session when initialization fails (4..300 seconds).
- * `time_wait_state` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare session timeout value in time-wait state. See the [`time_wait_state` arguments for tcp_session in flow] (#time_wait_state-arguments-for-tcp_session-in-flow) block.
+ * `time_wait_state` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare session timeout value in time-wait state. See the [`time_wait_state` arguments for tcp_session in flow] (#time_wait_state-arguments-for-tcp_session-in-flow) block.
---
#### forwarding_options arguments
@@ -148,6 +149,13 @@ The following arguments are supported:
* `session_ageout` - (Optional)(`Bool`) Allow session to ageout using service based timeout values.
* `session_timeout` - (Optional)(`Int`) Configure session timeout value for time-wait state (2..600 seconds).
+---
+#### feature_profile_web_filtering_juniper_enhanced_server arguments for utm
+* `host` - (Optional)(`String`) Server host IP address or string host name.
+* `port` - (Optional)(`Int`) Server port (1..65535).
+* `proxy_profile` - (Optional)(`String`) Proxy profile.
+* `routing_instance` - (Optional)(`String`) Routing instance name.
+
## Import
Junos security can be imported using any id, e.g.
diff --git a/website/docs/r/security_address_book.html.markdown b/website/docs/r/security_address_book.html.markdown
new file mode 100644
index 00000000..e95121e6
--- /dev/null
+++ b/website/docs/r/security_address_book.html.markdown
@@ -0,0 +1,85 @@
+---
+layout: "junos"
+page_title: "Junos: junos_security_address_book"
+sidebar_current: "docs-junos-resource-security-address-book"
+description: |-
+ Create a security address book (when Junos device supports it)
+---
+
+# junos_security_address_book
+
+Provides a security address book resource.
+
+## Example Usage
+
+```hcl
+# Add an address book with entries
+resource junos_security_address_book "testAddressBook" {
+ name = "testAddressBook"
+ attach_zone = ["SecurityZone"]
+ network_address {
+ name = "DemoNetworkAddress"
+ description = "Test Description"
+ value = "192.0.0.0/24"
+ }
+ network_address {
+ name = "DemoNetworkAddress2"
+ description = "Test Description 2"
+ value = "192.1.0.0/24"
+ }
+ dns_name {
+ name = "DemoDnsName"
+ value = "juniper.net"
+ }
+ range_address {
+ name = "DemoRangeAddress"
+ from = "192.0.0.1"
+ to = "192.0.0.10"
+ }
+ wildcard_address {
+ name = "DemoWildcardAddress"
+ value = "juniper.net"
+ }
+ address_set {
+ name = "DemoAddressSet"
+ address = ["DemoDnsName", "DemoWildcardAddress", "DemoRangeAddress"]
+ }
+}
+```
+
+## Argument Reference
+
+The following arguments are supported:
+
+* `name` - (Optional, Forces new resource)(`String`) The name of address book. Defaults to `global`.
+* `description` - (Optional)(`String`) The description of the address book.
+* `attach_zone` - (Optional)(`ListOfString`) List of zones to attach address book to. **NOTE:** Cannot be set on global address book.
+* `network_address` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified multiple times for each network address.
+ * `name` - (Required)(`String`) Name of network address.
+ * `description` - (Optional)(`String`) Description of network address.
+ * `value` - (Required)(`String`) CIDR value of network address. `192.0.0.0/24`
+* `wildcard_address` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified multiple times for each wildcard address.
+ * `name` - (Required)(`String`) Name of wildcard address.
+ * `description` - (Optional)(`String`) Description of network address.
+ * `value` - (Required)(`String`) Nework and Mask of wildcard address. `192.0.0.0/255.255.0.255`
+* `dns_name` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified multiple times for each dns name address.
+ * `name` - (Required)(`String`) Name of dns name address.
+ * `description` - (Optional)(`String`) Description of dns name address.
+ * `value` - (Required)(`String`) DNS name string value. `juniper.net`
+* `range_address` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified multiple times for each range address.
+ * `name` - (Required)(`String`) Name of range address.
+ * `description` - (Optional)(`String`) Description of range address.
+ * `from` - (Required)(`String`) IP address of start of range.
+ * `to` - (Required)(`String`) IP address of end of range.
+* `address_book_set` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified multiple times for each address-set to declare.
+ * `name` - (Required)(`String`) Name of address-set.
+ * `description` - (Optional)(`String`) Description of address-set.
+ * `address` - (Required)(`ListOfString`) List of address names.
+
+## Import
+
+Junos security address book can be imported using an id made up of ``, e.g.
+
+```sh
+$ terraform import junos_security_address_book.global global
+```
diff --git a/website/docs/r/security_global_policy.html.markdown b/website/docs/r/security_global_policy.html.markdown
new file mode 100644
index 00000000..c1cd8230
--- /dev/null
+++ b/website/docs/r/security_global_policy.html.markdown
@@ -0,0 +1,79 @@
+---
+layout: "junos"
+page_title: "Junos: junos_security_global_policy"
+sidebar_current: "docs-junos-resource-security-global-policy"
+description: |-
+ Configure static configuration in security policies global block
+---
+
+# junos_security_global_policy
+
+-> **Note:** This resource should only be created **once**. It's used to configure static (not object) options in `security policies global` block.
+
+Configure static configuration in `security policies global` block
+
+## Example Usage
+
+```hcl
+# Configure security policies global
+resource junos_security_global_policy "global" {
+ policy {
+ name = "test"
+ match_source_address = ["blue"]
+ match_destination_address = ["green"]
+ match_application = ["any"]
+ match_from_zone = ["any"]
+ match_to_zone = ["any"]
+ }
+ policy {
+ name = "drop"
+ match_source_address = ["blue"]
+ match_destination_address = ["any"]
+ match_application = ["any"]
+ match_from_zone = ["any"]
+ match_to_zone = ["any"]
+ then = "deny"
+ }
+}
+```
+
+## Argument Reference
+
+The following arguments are supported:
+
+* `policy` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified multiple times for each policy.
+ * `name` - (Required)(`String`) Security policy name.
+ * `match_source_address` - (Required)(`ListOfString`) List of source address match.
+ * `match_destination_address` - (Required)(`ListOfString`) List of destination address match.
+ * `match_application` - (Required)(`ListOfString`) List of applications match.
+ * `match_from_zone` - (Required)(`ListOfString`) Match multiple source zone.
+ * `match_to_zone` - (Required)(`ListOfString`) Match multiple destination zone.
+ * `then` - (Optional)(`String`) Action of policy. Defaults to `permit`.
+ * `count` - (Optional)(`Bool`) Enable count.
+ * `log_init` - (Optional)(`Bool`) Log at session init time.
+ * `log_close` - (Optional)(`Bool`) Log at session close time.
+ * `permit_application_services` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'permit application-services' configuration. See the [`permit_application_services` arguments] (#permit_application_services-arguments) block.
+
+---
+#### permit_application_services arguments
+* `application_firewall_rule_set` - (Optional)(`String`) Servie rule-set Name for Application firewall.
+* `application_traffic_control_rule_set` - (Optional)(`String`) Service rule-set name Application traffic control.
+* `gprs_gtp_profile` - (Optional)(`String`) Specify GPRS Tunneling Protocol profile name.
+* `gprs_sctp_profile` - (Optional)(`String`) Specify GPRS stream control protocol profile name.
+* `idp` - (Optional)(`Bool`) Enable Intrusion detection and prevention.
+* `redirect_wx` - (Optional)(`Bool`) Set WX redirection.
+* `reverse_redirect_wx` - (Optional)(`Bool`) Set WX reverse redirection.
+* `security_intelligence_policy` - (Optional)(`String`) Specify security-intelligence policy name.
+* `ssl_proxy` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to enable SSL Proxy.
+ * `profile_name` - (Optional)(`String`) Specify SSL proxy service profile name.
+* `uac_policy` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to enable unified access control enforcement.
+ * `captive_portal` - (Optional)(`String`) Specify captive portal.
+* `utm_policy` - (Optional)(`String`) Specify utm policy name.
+
+## Import
+
+Junos security global policies can be imported using any id, e.g.
+
+```
+$ terraform import junos_security_global_policy.global random
+```
diff --git a/website/docs/r/security_ike_gateway.html.markdown b/website/docs/r/security_ike_gateway.html.markdown
index 3562a937..1d4f506c 100644
--- a/website/docs/r/security_ike_gateway.html.markdown
+++ b/website/docs/r/security_ike_gateway.html.markdown
@@ -31,19 +31,19 @@ The following arguments are supported:
* `external_interface` - (Required)(`String`) Interface for ike negotiations.
* `policy` - (Required)(`String`) Ike policy.
* `address` - (Optional)(`ListOfString`) List of Peer IP. Need to set one of `address` or `dynamic_remote`.
-* `dynamic_remote` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare dynamic configuration. See the [`dynamic_remote` arguments] (#dynamic_remote-arguments) block. Need to set one of `address` or `dynamic_remote`.
-* `aaa` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'aaa' configuration.
+* `dynamic_remote` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare dynamic configuration. See the [`dynamic_remote` arguments] (#dynamic_remote-arguments) block. Need to set one of `address` or `dynamic_remote`.
+* `aaa` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'aaa' configuration.
* `access_profile` - (Optional)(`String`) Access profile that contains authentication information. Conflict with `aaa.client_*`.
* `client_password` - (Optional)(`String`) AAA client password with 1 to 128 characters. Conflict with `aaa.access_profile`.
* `client_username` - (Optional)(`String`) AAA client username with 1 to 128 characters. Conflict with `aaa.access_profile`.
-* `dead_peer_detection` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare RFC-3706 DPD configuration. See the [`dead_peer_detection` arguments] (#dead_peer_detection-arguments) block.
+* `dead_peer_detection` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare RFC-3706 DPD configuration. See the [`dead_peer_detection` arguments] (#dead_peer_detection-arguments) block.
* `general_ike_id` - (Optional)(`Bool`) Accept peer IKE-ID in general.
* `local_address` - (Optional)(`String`) Local IP for ike negotiations.
-* `local_identity` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare local IKE identity configuration.
+* `local_identity` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare local IKE identity configuration.
* `type` - (Required)(`String`) Type of IKE identity.
* `value` - (Optional)(`String`) Value for IKE identity.
* `no_nat_traversal` - (Optional)(`Bool`) Disable IPSec NAT traversal.
-* `remote_identity` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare remote IKE identity configuration.
+* `remote_identity` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare remote IKE identity configuration.
* `type` - (Required)(`String`) Type of IKE identity.
* `value` - (Optional)(`String`) Value for IKE identity.
* `version` - (Optional)(`String`) Negotiate using either IKE v1 or IKE v2 protocol. Need to be 'v1-only' or 'v2-only'.
@@ -52,7 +52,7 @@ The following arguments are supported:
#### dynamic_remote arguments
-> **Note:** You can only choose one argument between `distinguished_name`, `hostname`, `inet`, `inet6` and `user_at_hostname`.
* `connections_limit` - (Optional)(`Int`) Maximum number of users connected to gateway.
-* `distinguished_name` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare distinguished-name configuration.
+* `distinguished_name` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare distinguished-name configuration.
* `container` - (Optional)(`String`) Container string for a distinguished name.
* `wildcard` - (Optional)(`String`) Wildcard string for a distinguished name.
* `hostname` - (Optional)(`String`) Use a fully-qualified domain name.
diff --git a/website/docs/r/security_ipsec_vpn.html.markdown b/website/docs/r/security_ipsec_vpn.html.markdown
index 9602f5a4..653d3a67 100644
--- a/website/docs/r/security_ipsec_vpn.html.markdown
+++ b/website/docs/r/security_ipsec_vpn.html.markdown
@@ -36,7 +36,7 @@ The following arguments are supported:
Deprecated argument, use the `junos_interface_st0_unit` resource to find st0 unit available instead.
* `df_bit` - (Optional)(`String`) Specifies how to handle the Don't Fragment bit. Need to be 'clear', 'copy' or 'set'.
* `establish_tunnels` - (Optional)(`String`) When the VPN comes up. Need to be 'immediately' or 'on-traffic'.
-* `ike` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare ike configuration.
+* `ike` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare ike configuration.
* `gateway` - (Required)(`String`) The name of security ike gateway (phase-1).
* `policy` - (Required)(`String`) The name of ipsec policy.
* `identity_local` - (Optional)(`String`) IPSec proxy-id local parameter.
@@ -46,7 +46,7 @@ Deprecated argument, use the `junos_interface_st0_unit` resource to find st0 uni
* `name` - (Required)(`String`) Name of traffic-selector.
* `local_ip` - (Required)(`String`) CIDR for IP addresses of local traffic-selector.
* `remote_ip` - (Required)(`String`) CIDR for IP addresses of remote traffic-selector.
-* `vpn_monitor` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare VPN monitor liveness configuration.
+* `vpn_monitor` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare VPN monitor liveness configuration.
* `destination_ip` - (Optional)(`String`) IP destination for monitor message.
* `optimized` - (Optional)(`Bool`) Optimize for scalability.
* `source_interface` - (Optional)(`String`) Set source interface for monitor message. Compute when `source_interface_auto` = true.
diff --git a/website/docs/r/security_nat_destination.html.markdown b/website/docs/r/security_nat_destination.html.markdown
index 81e364a7..2229008d 100644
--- a/website/docs/r/security_nat_destination.html.markdown
+++ b/website/docs/r/security_nat_destination.html.markdown
@@ -36,7 +36,7 @@ resource junos_security_nat_destination "demo_dnat" {
The following arguments are supported:
* `name` - (Required, Forces new resource)(`String`) The name of destination nat.
-* `from` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'from' configuration.
+* `from` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'from' configuration.
* `type` - (Required)(`String`) Type of from options. Need to be 'interface', 'routing-instance' or 'zone'
* `value` - (Required)(`String`) Name of interface, routing-instance or zone for from options
* `rule` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified multiple times for each rule to declare. See the [`rule` arguments](#rule-arguments) block.
@@ -45,7 +45,7 @@ The following arguments are supported:
#### rule arguments
* `name` - (Required)(`String`) Name of rule
* `destination_address` - (Required)(`String`) CIDR for match destination address
-* `then` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'then' action.
+* `then` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'then' action.
* `type` - (Required)(`String`) Type of destination nat. Need to be 'pool' or 'off'
* `pool` - (Optional)(`String`) Name of nat destination pool when type pool
diff --git a/website/docs/r/security_nat_source.html.markdown b/website/docs/r/security_nat_source.html.markdown
index eac3bc65..3b76a0ee 100644
--- a/website/docs/r/security_nat_source.html.markdown
+++ b/website/docs/r/security_nat_source.html.markdown
@@ -42,10 +42,10 @@ resource junos_security_nat_source "demo_snat" {
The following arguments are supported:
* `name` - (Required, Forces new resource)(`String`) The name of source nat.
-* `from` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'from' configuration.
+* `from` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'from' configuration.
* `type` - (Required)(`String`) Type of from options. Need to be 'interface', 'routing-instance' or 'zone'.
* `value` - (Required)(`String`) Name of interface, routing-instance or zone for from options.
-* `to` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'to' configuration.
+* `to` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'to' configuration.
* `type` - (Required)(`String`) Type of to options. Need to be 'interface', 'routing-instance' or 'zone'.
* `value` - (Required)(`String`) Name of interface, routing-instance or zone for to options.
* `rule` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified multiple times for each rule to declare. See the [`rule` arguments](#rule-arguments) block.
@@ -53,11 +53,11 @@ The following arguments are supported:
---
#### rule arguments
* `name` - (Required)(`String`) Name of rule.
-* `match` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'match' configuration.
+* `match` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'match' configuration.
* `destination_address` - (Optional)(`ListOfString`) CIDR list to match destination address.
* `protocol` - (Optional)(`ListOfString`) Protocol list to match.
* `source_address` - (Optional)(`ListOfString`) CIDR list to match source address.
-* `then` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'then' configuration.
+* `then` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'then' configuration.
* `type` - (Required)(`String`) Type of source nat. Need to be 'interface', 'pool' or 'off'.
* `pool` - (Optional)(`String`) Name of nat source pool when type pool.
diff --git a/website/docs/r/security_nat_static.html.markdown b/website/docs/r/security_nat_static.html.markdown
index 24e7ba5d..cb9af19d 100644
--- a/website/docs/r/security_nat_static.html.markdown
+++ b/website/docs/r/security_nat_static.html.markdown
@@ -36,7 +36,7 @@ resource junos_security_nat_static "demo_nat" {
The following arguments are supported:
* `name` - (Required, Forces new resource)(`String`) The name of static nat.
-* `from` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'from' configuration.
+* `from` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'from' configuration.
* `type` - (Required)(`String`) Type of from options. Need to be 'interface', 'routing-instance' or 'zone'.
* `value` - (Required)(`String`) Name of interface, routing-instance or zone for from options.
* `rule` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified multiple times for each rule to declare. See the [`rule` arguments](#rule-arguments) block.
@@ -45,7 +45,7 @@ The following arguments are supported:
#### rule arguments
* `name` - (Required)(`String`) Name of rule.
* `destination_address` - (Required)(`String`) CIDR of destination address for rule.
-* `then` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'then' configuration.
+* `then` - (Required)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'then' configuration.
* `type` - (Required)(`String`) Type of static nat. Need to be 'inet' or 'prefix'.
* `prefix` - (Optional)(`String`) CIDR for prefix static nat.
* `routing_instance` - (Optional)(`String`) Change routing_instance with nat.
diff --git a/website/docs/r/security_policy.html.markdown b/website/docs/r/security_policy.html.markdown
index 3b7aa846..e420e913 100644
--- a/website/docs/r/security_policy.html.markdown
+++ b/website/docs/r/security_policy.html.markdown
@@ -37,7 +37,7 @@ The following arguments are supported:
* `match_source_address` - (Required)(`ListOfString`) List of source address match.
* `match_destination_address` - (Required)(`ListOfString`) List of destination address match.
* `match_application` - (Required)(`ListOfString`) List of applications match.
- * `then` - (Optional)(`String`) action of policy. Defaults to `permit`.
+ * `then` - (Optional)(`String`) Action of policy. Defaults to `permit`.
* `count` - (Optional)(`Bool`) Enable count.
* `log_init` - (Optional)(`Bool`) Log at session init time.
* `log_close` - (Optional)(`Bool`) Log at session close time.
@@ -55,7 +55,7 @@ The following arguments are supported:
* `reverse_redirect_wx` - (Optional)(`Bool`) Set WX reverse redirection.
* `security_intelligence_policy` - (Optional)(`String`) Specify security-intelligence policy name.
* `ssl_proxy` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html) Enable SSL Proxy. Max of 1.
- * `profile_name` - (Optional)(`String`) Specify SSL proxy service profile name.
+ * `profile_name` - (Optional)(`String`) Specify SSL proxy service profile name.
* `uac_policy` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html) Enable unified access control enforcement. Max of 1.
* `captive_portal` - (Optional)(`String`) Specify captive portal.
* `utm_policy` - (Optional)(`String`) Specify utm policy name.
diff --git a/website/docs/r/security_screen.html.markdown b/website/docs/r/security_screen.html.markdown
index ea5ba2fc..53c1c825 100644
--- a/website/docs/r/security_screen.html.markdown
+++ b/website/docs/r/security_screen.html.markdown
@@ -45,13 +45,13 @@ The following arguments are supported:
* `name` - (Required, Forces new resource)(`String`) The name of screen.
* `alarm_without_drop` - (Optional)(`Bool`) Do not drop packet, only generate alarm.
* `description` - (Optional)(`String`) Text description of screen.
-* `icmp` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'icmp' configuration. See the [`icmp` arguments] (#icmp-arguments) block.
-* `ip` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'ip' configuration. See the [`ip` arguments] (#ip-arguments) block.
-* `limit_session` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'limit-session' configuration.
+* `icmp` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'icmp' configuration. See the [`icmp` arguments] (#icmp-arguments) block.
+* `ip` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'ip' configuration. See the [`ip` arguments] (#ip-arguments) block.
+* `limit_session` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'limit-session' configuration.
* `destination_ip_based` - (Optional)(`ListOfString`) Limit sessions to the same destination IP (1..2000000).
* `source_ip_based` - (Optional)(`ListOfString`) Limit sessions from the same source IP (1..2000000).
-* `tcp` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'tcp' configuration. See the [`tcp` arguments] (#tcp-arguments) block.
-* `udp` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'udp' configuration. See the [`udp` arguments] (#udp-arguments) block.
+* `tcp` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'tcp' configuration. See the [`tcp` arguments] (#tcp-arguments) block.
+* `udp` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'udp' configuration. See the [`udp` arguments] (#udp-arguments) block.
---
#### icmp arguments
@@ -68,7 +68,7 @@ The following arguments are supported:
#### ip arguments
* `bad_option` - (Optional)(`Bool`) Enable ip with bad option ids option.
* `block_frag` - (Optional)(`Bool`) Enable ip fragment blocking ids option.
-* `ipv6_extension_header` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'ip ipv6-extension-header' configuration. See the [`ipv6_extension_header` arguments for ip] (#ipv6_extension_header-arguments-for-ip) block.
+* `ipv6_extension_header` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'ip ipv6-extension-header' configuration. See the [`ipv6_extension_header` arguments for ip] (#ipv6_extension_header-arguments-for-ip) block.
* `ipv6_extension_header_limit` - (Optional)(`Int`) Enable ipv6 extension header limit ids option (0..32).
* `ipv6_malformed_header` - (Optional)(`Bool`) Enable ipv6 malformed header ids option.
* `loose_source_route_option` - (Optional)(`Bool`) Enable ip with loose source route ids option.
@@ -80,7 +80,7 @@ The following arguments are supported:
* `strict_source_route_option` - (Optional)(`Bool`) Enable ip with strict source route ids option.
* `tear_drop` - (Optional)(`Bool`) Enable tear drop ids option.
* `timestamp_option` - (Optional)(`Bool`) Enable ip with timestamp option ids option.
-* `tunnel` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'ip tunnel' configuration. See the [`tunnel` arguments for ip] (#tunnel-arguments-for-ip) block.
+* `tunnel` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'ip tunnel' configuration. See the [`tunnel` arguments for ip] (#tunnel-arguments-for-ip) block.
* `unknown_protocol` - (Optional)(`Bool`) Enable ip unknown protocol ids option.
---
@@ -138,13 +138,13 @@ The following arguments are supported:
---
#### tunnel arguments for ip
* `bad_inner_header` - (Optional)(`Bool`) Enable IP tunnel bad inner header ids option.
-* `gre` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'ip tunnel gre' configuration.
+* `gre` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'ip tunnel gre' configuration.
* `gre_4in4` - (Optional)(`Bool`) Enable IP tunnel GRE 4in4 ids option.
* `gre_4in6` - (Optional)(`Bool`) Enable IP tunnel GRE 4in6 ids option.
* `gre_6in4` - (Optional)(`Bool`) Enable IP tunnel GRE 6in4 ids option.
* `gre_6in6` - (Optional)(`Bool`) Enable IP tunnel GRE 6in6 ids option.
* `ip_in_udp_teredo` - (Optional)(`Bool`) Enable IP tunnel IPinUDP Teredo ids option.
-* `ipip` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'ip tunnel ipip' configuration.
+* `ipip` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'ip tunnel ipip' configuration.
* `ipip_4in4` - (Optional)(`Bool`) Enable IP tunnel IPIP 4in4 ids option.
* `ipip_4in6` - (Optional)(`Bool`) Enable IP tunnel IPIP 4in6 ids option.
* `ipip_6in4` - (Optional)(`Bool`) Enable IP tunnel IPIP 6in4 ids option.
diff --git a/website/docs/r/system.html.markdown b/website/docs/r/system.html.markdown
index 1cdb6238..309b03eb 100644
--- a/website/docs/r/system.html.markdown
+++ b/website/docs/r/system.html.markdown
@@ -43,11 +43,11 @@ The following arguments are supported:
* `default_address_selection` - (Optional)(`Bool`) Use loopback interface as source address for locally generated packets.
* `domain_name` - (Optional)(`String`) Domain name.
* `host_name` - (Optional)(`String`) Hostname.
-* `inet6_backup_router` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'inet6-backup-router' configuration.
+* `inet6_backup_router` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'inet6-backup-router' configuration.
* `address` - (Optional)(`String`) Address of router to use while booting.
* `destination` - (Optional)(`ListOfString`) Destination networks reachable through the router.
-* `internet_options` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'internet-options' configuration. See the [`internet_options` arguments] (#internet_options-arguments) block.
-* `login` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'login' configuration. See the [`login` arguments] (#login-arguments) block.
+* `internet_options` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'internet-options' configuration. See the [`internet_options` arguments] (#internet_options-arguments) block.
+* `login` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'login' configuration. See the [`login` arguments] (#login-arguments) block.
* `max_configuration_rollbacks` - (Optional)(`Int`) Maximum rollback configuration (0..49).
* `max_configurations_on_flash` - (Optional)(`Int`) Number of configuration files stored on flash (0..49).
* `name_server` - (Optional)(`ListOfString`) DNS name servers.
@@ -56,10 +56,10 @@ The following arguments are supported:
* `no_ping_time_stamp` - (Optional)(`Bool`) Do not insert time stamp in ping replies.
* `no_redirects` - (Optional)(`Bool`) Disable ICMP redirects.
* `no_redirects_ipv6` - (Optional)(`Bool`) Disable IPV6 ICMP redirects.
-* `services` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'services' configuration.
- * `ssh` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'ssh' configuration. See the [`ssh` arguments for services] (#ssh-arguments-for-services) block.
-* `syslog` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'syslog' configuration.
- * `archive` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'archive' configuration. See the [`archive` arguments for syslog] (#archive-arguments-for-syslog) block.
+* `services` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'services' configuration.
+ * `ssh` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'ssh' configuration. See the [`ssh` arguments for services] (#ssh-arguments-for-services) block.
+* `syslog` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'syslog' configuration.
+ * `archive` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'archive' configuration. See the [`archive` arguments for syslog] (#archive-arguments-for-syslog) block.
* `log_rotate_frequency` - (Optional)(`Int`) Rotate log frequency (1..59 minutes).
* `source_address` - (Optional)(`String`) Use specified address as source address.
* `time_zone` - (Optional)(`String`) Time zone name or POSIX-compliant time zone string (/ or ).
@@ -68,10 +68,10 @@ The following arguments are supported:
---
#### internet_options arguments
* `gre_path_mtu_discovery` - (Optional)(`Bool`) Enable path MTU discovery for GRE tunnels. Conflict with `no_gre_path_mtu_discovery`.
-* `icmpv4_rate_limit` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'icmpv4-rate-limit' configuration.
+* `icmpv4_rate_limit` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'icmpv4-rate-limit' configuration.
* `bucket_size` - (Optional)(`Int`) ICMP rate-limiting maximum bucket size (seconds).
* `packet-rate` - (Optional)(`Int`) ICMP rate-limiting packets earned per second.
-* `icmpv6_rate_limit` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'icmpv6-rate-limit' configuration.
+* `icmpv6_rate_limit` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'icmpv6-rate-limit' configuration.
* `bucket_size` - (Optional)(`Int`) ICMPv6 rate-limiting maximum bucket size (seconds).
* `packet-rate` - (Optional)(`Int`) ICMPv6 rate-limiting packets earned per second.
* `ipip_path_mtu_discovery` - (Optional)(`Bool`) Enable path MTU discovery for IP-IP tunnels. Conflict with `no_ipip_path_mtu_discovery`.
@@ -100,7 +100,7 @@ The following arguments are supported:
* `deny_sources_address` - (Optional)(`ListOfString`) Sources from which logins are denied.
* `idle_timeout` - (Optional)(`Int`) Maximum idle time before logout (1..60 minutes).
* `message` - (Optional)(`String`) System login message.
-* `password` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'password' configuration.
+* `password` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'password' configuration.
* `change_type` - (Optional)(`String`) Password change type.
* `format` - (Optional)(`String`) Encryption method to use for password.
* `maximum_length` - (Optional)(`Int`) Maximum password length for all users (20..128).
@@ -112,7 +112,7 @@ The following arguments are supported:
* `minimum_punctuations` - (Optional)(`Int`) Minimum number of punctuation class characters in password (1..128).
* `minimum_reuse` - (Optional)(`Int`) Minimum number of old passwords which should not be same as the new password (1..20).
* `minimum_upper_cases` - (Optional)(`Int`) Minimum number of upper-case class characters in password (1..128).
-* `retry_options` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'retry-options' configuration.
+* `retry_options` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'retry-options' configuration.
* `backoff_factor` - (Optional)(`Int`) Delay factor after 'backoff-threshold' password failures (5..10).
* `backoff_threshold` - (Optional)(`Int`) Number of password failures before delay is introduced (1..3).
* `lockout_period` - (Optional)(`Int`) Amount of time user account is locked after 'tries-before-disconnect' failures (1..43200 minutes).
diff --git a/website/docs/r/system_login_user.html.markdown b/website/docs/r/system_login_user.html.markdown
index d0ca7ca0..83ee11bd 100644
--- a/website/docs/r/system_login_user.html.markdown
+++ b/website/docs/r/system_login_user.html.markdown
@@ -30,7 +30,7 @@ The following arguments are supported:
* `name` - (Required, Forces new resource)(`String`) The name of system login user.
* `class` - (Required)(`String`) Login class.
* `uid` - (Optional, Computed, Forces new resource)(`Int`) User identifier (uid) (100..64000).
-* `authentication` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare 'authentication' configuration.
+* `authentication` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare 'authentication' configuration.
* `encrypted_password` - (Optional)(`String`) Encrypted password string.
* `no_public_keys` - (Optional)(`Bool`) Disables ssh public key based authentication.
* `ssh_public_keys` - (Optional)(`ListOfString`) Secure shell (ssh) public key string.
diff --git a/website/docs/r/vlan.html.markdown b/website/docs/r/vlan.html.markdown
index 9704ac9f..e1f1f527 100644
--- a/website/docs/r/vlan.html.markdown
+++ b/website/docs/r/vlan.html.markdown
@@ -37,7 +37,7 @@ The following arguments are supported:
* `service_id` - (Optional)(`Int`) Service id (when Junos device supports it).
* `vlan_id` - (Optional)(`Int`) 802.1q VLAN identifier. Conflict with `vlan_id_list`.
* `vlan_id_list` - (Optional)(`ListOfString`) List of vlan ID. Can be a ID or range (exemple: 10-20). Conflict with `vlan_id`.
-* `vxlan` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once for declare vxlan configuration (when Junos device supports it).
+* `vxlan` - (Optional)([attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html)) Can be specified only once to declare vxlan configuration (when Junos device supports it).
* `vni` - (Required)(`Int`) VXLAN identifier.
* `encapsulate_inner_vlan` - (Optional)(`Bool`) Retain inner VLAN in the packet.
* `ingress_node_replication` - (Optional)(`Bool`) Enable ingress node replication.
diff --git a/website/junos.erb b/website/junos.erb
index 3948cc88..abe519f0 100644
--- a/website/junos.erb
+++ b/website/junos.erb
@@ -33,12 +33,18 @@
>
junos_bgp_neighbor
+ >
+ junos_chassis_cluster
+
>
junos_firewall_filter
>
junos_firewall_policer
+ >
+ junos_group_dual_system
+
>
junos_interface
@@ -51,6 +57,9 @@
>
junos_interface_st0_unit
+ >
+ junos_null_commit_file
+
>
junos_ospf_area
@@ -81,6 +90,12 @@
>
junos_security
+ >
+ junos_security_address_book
+
+ >
+ junos_security_global_policy
+
>
junos_security_ike_gateway
@@ -123,6 +138,12 @@
>
junos_security_policy_tunnel_pair_policy
+ >
+ junos_security_screen
+
+ >
+ junos_security_screen_whitelist
+
>
junos_security_utm_custom_url_category