diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/.DS_Store differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..79db101 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# iac-vastcluster-ansible-demo + +## Requirements + +ansible [core 2.13.6] + +## Hosts + +Edit Hosts in the `./hosts` file following the `[virtual_clusters]` example, Delete if not applicable + +## Host Vars + +Create a new .yml file under the host_vars dir with the same name of your newly added host in the hosts file. e.g. `example-cluster` + +Follow the examples given in `example-cluster.yml` + +## Secrets + +Encrypted variables such as passwords or api tokens can be kept in the `secrets.yml` + +Editing File: `ansible-vault edit secrets.yml` +Example passphrase: `vastdata` + +## Run All Roles in Initial Playbook for a specific host + +`ansible-playbook -i hosts initial.yml --ask-vault-pass --limit example-cluster` + +## Run Specific Role in Initial Playbook for a specific host + +`ansible-playbook -i hosts initial.yml --ask-vault-pass --limit example-cluster --tags setup-protectionpolicies` diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..caef727 --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,6 @@ +[defaults] +roles_path = roles +collection_path = collections +stdout_callback = yaml +display_ok_hosts = true +host_key_checking = false diff --git a/host_vars/sales-devvm-brett-dellandre.yml b/host_vars/sales-devvm-brett-dellandre.yml new file mode 100644 index 0000000..62f9d26 --- /dev/null +++ b/host_vars/sales-devvm-brett-dellandre.yml @@ -0,0 +1,209 @@ +--- +## This is an example host_var file for a host named "example-cluster" in the hosts file. +## This file will provide all variables needed to properly execute any or all of the (5) Roles: +## Views, View Policies, Quotas, Protection Policies, and Protected Paths. + +## Edit the vms_ip for your cluster's Vast Management Service (VMS) IP or FQDN +vms_ip: 172.31.58.119 +## Edit the cluster_name for your cluster's name, displayed in the top left of the webui after login +cluster_name: sales-devvm-brett-dellandre + +## Each set of variables below has a variable to be defined labeled 'method' this is the HTTP Request method +## used to create/edit/delete the Role. +## Accepted definitions for Method are: POST (create), PATCH (modify), and DELETE (remove). + +## This set of variables will provide the input to execute the Views Role and will create (1) View(s). +views: +## +## Required Variables: +## +# Accepted definitions for Method are: POST (create), PATCH (modify), and DELETE (remove). + - method: POST +# The full Element Store path to from the top level of the storage system on the cluster to the location that you want to expose. Begin with ‘/’. Do not include a trailing slash. + path: /example_view_path +# Protocols exposed by this view. Can be one or more of NFS, NFS4, SMB, S3 and/or ENDPOINT. + protocols: NFS,NFS4 +# Create a directory at the specified path. Set to true if the specified path does not exist. + create_dir: true +# Enter the View Policy name to be used for this View. + view_policy_name: example_view_policy +## +## Optional Variables (dependent on protocol(s) selected): +## +# Indicates whether the view should support simultaneous access to NFS3/NFS4/SMB protocols. Can be one of BOTH_NFS3_AND_NFS4_INTEROP_DISABLED, ONLY_NFS3_INTEROP_ENABLED, ONLY_NFS4_INTEROP_ENABLED, or BOTH_NFS3_AND_NFS4_INTEROP_ENABLED + nfs_interop_flags: BOTH_NFS3_AND_NFS4_INTEROP_ENABLED +# Relevant if NFS is included in the protocols array. An alias for the mount path of an NFSv3 export. The alias must begin with a forward slash (‘/’) and must consist of only ASCII characters. If specified, the alias that can be used by NFSv3 clients to mount the view. + alias: /example_nfs_export_name +# SMB share name. Must be specified if SMB is specified in protocols. +# share: example_smb_share_name +# A name for the S3 bucket name. Must be specified if S3 bucket is specified in protocols. +# bucket: example_s3_bucket_name +# Specifies a user to be the bucket owner. Specify as user name. Must be specified if S3 Bucket is included in protocols. + bucket_owner: example_s3_bucket_owner_name +# Set to true to enable object locking on an S3 bucket. Object locking cannot be disabled after the view is created. Must be true if s3_versioning is true. + s3_locks: false +# Relevant if object locking is enabled. Specifies a default retention period for objects in the bucket. If set, object versions that are placed in the bucket are automatically protected with the specified retention lock. Otherwise, by default, each object version has no automatic protection but can be configured with a retention period or legal hold. Specify as an integer followed by d for day, m for month, y for year. Such as 2d or 1y. + s3_locks_retention_period: 1d +# Enable S3 Versioning if S3 bucket. Versioning cannot be disabled after the view is created. + s3_versioning: false +# S3 Unverified Lookup + s3_unverified_lookup: false +# For S3 endpoint views, specify a list of users, by user name, whose bucket create requests use this view. Any request to create an S3 bucket that is sent by S3 API by a specified user will use this S3 Endpoint view. Users should not be specified as bucket creators in more than one S3 Endpoint view. Naming a user as a bucket creator in two S3 Endpoint views will fail the creation of the view with an error. + bucket_creators: example_s3_bucket_creators_name +# For S3 endpoint views, specify a list of groups, by group name, whose bucket create requests use this view. Any request to create an S3 bucket that is sent by S3 API by a user who belongs to a group listed here will use this S3 Endpoint view. Take extra care not to duplicate bucket creators through groups: If you specify a group as a bucket creator group in one view and you also specify a user who belongs to that group as a bucket creator user in another view, view creation will not fail. Yet, there is a conflict between the two configurations and the selection of a view for configuring the user’s buckets is not predictable. + bucket_creators_groups: example_s3_bucket_creators_group_name +# Allow S3 anonymous access to S3 bucket. If true, anonymous requests are granted provided that the object ACL grants access to the All Users group (in S3 Native security flavor) or the permission mode bits on the requested file and directory path grant access permission to ‘others’ (in NFS security flavor). + allow_s3_anonymous_access: false + + +## This set of variables will provide the input to execute the View Policies Role and will create (1) View Policy. +viewpolicies: +## +## Required Variables: +## +# Accepted definitions for Method are: POST (create), PATCH (modify), and DELETE (remove). + - method: POST +# Name of the View Policy to be created, modified or deleted. + name: example_view_policy +# Specifies the security flavor, which determines how file and directory permissions are applied in multiprotocol views. Can only be one of NFS, SMB, S3_NATIVE or MIXED_LAST_WINS. + flavor: NFS +# Specifies which source is trusted for the user’s group memberships, when users’ access to the view is authorized. Can only be one of RCP, PROVIDERS or RPC_AND_PROVIDERS + auth_source: RPC_AND_PROVIDERS +# Specifies the policy for limiting file path component name length. Can only be one of LCD for Least Common Denominator or NPL for Native Protocol Limit. + path_length: LCD +# Specifies the policy for which characters are allowed in file names. Can only be one of LCD for Least Common Denominator or NPL for Native Protocol Limit. + allowed_characters: LCD +## +## Optional Variables (dependent on security flavor selected): +## +# Sets the VAST Cluster’s NFS server to use 32bit file IDs. This setting supports legacy 32-bit applications running over NFS. + use_32bit_fileid: false +# Specifies how files receive their owning group when they are created. Can only be one of LINUX or BSD + gid_inheritance: LINUX +# Frequency for updating the atime attribute of NFS files. atime is updated on read operations if the difference between the current time and the file’s atime value is greater than the atime frequency. Specify as time in seconds. + atime_frequency: +# Enables full support of extended POSIX Access Control Lists (ACL). + nfs_posix_acl: false +# Specify which NFS client hosts have no squash. With no squash, all operations are supported. Use this option if you trust the root user not to perform operations that will corrupt data. Specify array of hosts separated by commas. Each host can be specified as an IP address, a netgroup key beginning with @, a CIDR subnet or a range of IPs indicated by an IP address with a * as a wildcard in place of any of the 8-bit fields in the IP address. + nfs_no_squash: [] +# Specify which NFS client hosts have root squash. With root squash, the root user is mapped to nobody for all file and folder management operations on the export. This enables you to prevent the strongest super user from corrupting all user data on the VAST Cluster. Specify array of hosts separated by commas. Each host can be specified as an IP address, a netgroup key beginning with @, a CIDR subnet or a range of IPs indicated by an IP address with a * as a wildcard in place of any of the 8-bit fields in the IP address. + nfs_root_squash: ["*"] +# Specify which NFS client hosts have all squash. With all squash, all client users are mapped to nobody for all file and folder management operations on the export. Specify array of hosts separated by commas. Each host can be specified as an IP address, a netgroup key beginning with @, a CIDR subnet or a range of IPs indicated by an IP address with a * as a wildcard in place of any of the 8-bit fields in the IP address. + nfs_all_squash: [] +# Specify which NFS client hosts can access the trash folder. Specify array of hosts separated by commas. Each host can be specified as an IP address, a CIDR subnet or a range of IPs indicated by an IP address with a * as a wildcard in place of any of the 8-bit fields in the IP address. Trash folder access must also be enabled for the cluster. + trash_access: [] +# Specify which NFS client hosts can access the view with read-write access. Specify array of hosts separated by commas. Each host can be specified as an IP address, a netgroup key beginning with @, a CIDR subnet or a range of IPs indicated by an IP address with a * as a wildcard in place of any of the 8-bit fields in the IP address. + nfs_read_write: [] +# Specify which NFS client hosts can access the view with read-only access. Specify array of hosts separated by commas. Each host can be specified as an IP address, a netgroup key beginning with @, a CIDR subnet or a range of IPs indicated by an IP address with a * as a wildcard in place of any of the 8-bit fields in the IP address. + nfs_read_only: ["*"] +# If enabled for NFS-exposed views, the NFS server unilaterally returns open (777) permission for all files and directories when responding to client side access checks. + nfs_return_open_permissions: +# Specify which SMB client hosts can access the view with read-write access. Specify array of hosts separated by commas. Each host can be specified as an IP address, a netgroup key beginning with @, a CIDR subnet or a range of IPs indicated by an IP address with a * as a wildcard in place of any of the 8-bit fields in the IP address. + smb_read_write: ["*"] +# Specify which SMB client hosts can access the view with read-only access. Specify array of hosts separated by commas. Each host can be specified as an IP address, a CIDR subnet or a range of IPs indicated by an IP address with a * as a wildcard in place of any of the 8-bit fields in the IP address. + smb_read_only: [] +# Specify which S3 client hosts can access the view with read-write access. Specify array of hosts separated by commas. Each host can be specified as an IP address, a CIDR subnet or a range of IPs indicated by an IP address with a * as a wildcard in place of any of the 8-bit fields in the IP address. + s3_read_write: ["*"] +# For multiprotocol views, if the security flavor is NFS, this parameter sets default unix permission bits for files created by SMB clients. Use three digit numeric notation, each digit representing the user, group and others compontents of the permissions, in that order. Each digit is the sum of the read bit, write bit and execute bit. If reading is permitted, the read bit adds 4 to the component. If writing is permitted, the write bit adds 2 to the component. If execution is permitted, the execute bit adds 1 to the component. 644 is the default. + smb_file_mode: 644 +# For multiprotocol views, if the security flavor is NFS, this parameter sets default unix permission bits for directories created by SMB clients. Use three digit numeric notation, each digit representing the user, group and others compontents of the permissions, in that order. Each digit is the sum of the read bit, write bit and execute bit. If reading is permitted, the read bit adds 4 to the component. If writing is permitted, the write bit adds 2 to the component. If execution is permitted, the execute bit adds 1 to the component. 755 is the default. + smb_directory_mode: 755 +# Specify which S3 client hosts can access the view with read-only access. Specify array of hosts separated by commas. Each host can be specified as an IP address, a CIDR subnet or a range of IPs indicated by an IP address with a * as a wildcard in place of any of the 8-bit fields in the IP address. + s3_read_only: [] +# Users with permission to list buckets that are created using this policy even if they do not have permission to access those buckets. + s3_visibility: [] +# Users with permission to list buckets that are created using this policy even if they do not have permission to access those buckets. + s3_visibility_groups: [] +# For use when connecting from Mac clients to SMB shares, this option enables Security IDs (SIDs) to be returned in Apple compatible representation. + apple_sid: true +# Dedicate VIP Pools to the view policy. Specify VIP Pool IDs in a comma separated list. + vip_pool_name: +# For a policy intended for use with NFSv4.1-enabled views, sets the Minimal Protection Level for NFSv4.1 client mounts: ‘KRB_AUTH_ONLY’ allows client mounts with Kerberos authentication only (using the RPCSEC_GSS authentication service), ‘SYSTEM’ allows client mounts using either the AUTH_SYS RCP security flavor (the traditional default NFS authentication scheme) or with Kerberos authentication, ‘NONE’ (default) allows client mounts with the AUTH_NONE (anonymous access), or AUTH_SYS RCP security flavors, or with Kerberos authentication. + nfs_minimal_protection_level: NONE + protocols_audit: +# Audit Create/Delete Files/Directories/Objects + - data_create_delete: false +# Audit Modify data/MD operations + data_modify: false +# Audit Read data operations + data_read: false +# Log full path + log_full_path: false +# Log hostname + log_hostname: false +# Log username + log_username: false +# Log deleted files/dirs from trash dir + log_deleted: false +# Array of protocols to audit. Can be one or more of NFSv3 and SMB + protocols: NFSv3,SMB + + +## This set of variables will provide the input to execute the Quotas Role and will create (1) Quota. +quotas: +## +## Required Variables: +## +# Accepted definitions for Method are: POST (create), PATCH (modify), and DELETE (remove). + - method: POST +# A name for the Quota. + name: example_quota_name +# The directory path on which to enforce the quota. + path: /example_view_path +## +## Optional Variables (dependent on security flavor selected): +## +# Set to true to create the directory if the directory was not created yet. + create_dir: false +# Storage usage limit at which warnings of exceeding the quota are issued. + soft_limit_capacity: 90 TB +# Storage usage limit beyond which no writes will be allowed. + hard_limit_capacity: 100 TB +# Number of directories and unique files under the path at which warnings of exceeding the quota will be issued. A file with multiple hardlinks is counted only once. + soft_limit_folders: 90000 +# Number of directories and unique files under the path beyond which no writes will be allowed. A file with multiple hardlinks is counted only once. + hard_limit_folders: 100000 +# Quota enforcement grace period in seconds, minutes, hours or days. Example: 90m + grace_period: 90m +# Enables alarms on relevant events for user and group quotas. Applicable only if is_user_quota is true. Raises alarms reporting the number of users that exceed their quotas and when one or more users is/are blocked from writing to the quota directory. + enable_alarms: true +# Set to true to enable querying Active Directory and LDAP services for user emails when sending user notifications to users if they exceed their user/group quota limits. If enabled, the provider query is the first priority source for a user’s email. If a user’s email is not found on the provider, a global suffix is used to form an email. If no suffix is set, default_email is used. + enable_email_providers: true +# Emails are sent to users if and when they exceed their user/group quota limits. default_email is a default email address that is used instead of a user’s email address in the event that no email address is found for the user on a provider and no email suffix is set. + default_email: +# Set to true to enable user and group quotas. False by default. Cannot be disabled later. + is_user_quota: false + +## This set of variables will provide the input to execute the Protection Policies Role and will create (1) Protection Policy. +protectionpolicies: +# Accepted definitions for Method are: POST (create), PATCH (modify), and DELETE (remove). + - method: POST +# A name for the Protection Policy. + name: example_protection_policy +# Defines the schedule for snapshot creation and the local and remote retention policies. The interval to create snapshots numberical value. + every_value: 15 +# Defines the schedule for snapshot creation and the local and remote retention policies. The interval to create snapshots in (s)econds, (m)inutes, (h)ours, (D)ays, (w)eeks, (M)onths or (y)ears. + every_unit: m +# Defines the schedule for snapshot creation and the local and remote retention policies. The numerical value of how long to retain snapshots. + keep_local_value: 1 +# Defines the schedule for snapshot creation and the local and remote retention policies. How long to keep local snapshots in (m)inutes, (h)ours, (D)ays, (w)eeks, (M)onths or (y)ears. + keep_local_period: D +# The prefix for names of snapshots created by the policy + snapshot_prefix: example_snapshot_prefix +# Specify the type of data protection. CLOUD_REPLICATION is S3 backup. LOCAL means local snapshots without replication. + clone_type: local +# Set to true to protect the protection policy from accidental or malicious deletion with the indestructibility feature. If this setting is enabled, authorized unlocking of the cluster’s indestructibility mechanism is required to do any of the following: modifying the policy, deleting the policy or disabling this setting. + indestructible: false + +## This set of variables will provide the input to execute the Protected Paths Role and will create (1) Protected Path. +protectedpaths: +# Accepted definitions for Method are: POST (create), PATCH (modify), and DELETE (remove). + - method: POST +# Name of the Protected Path + name: example_protected_path +# Name of the Protection Policy to use + protection_policy_name: example_protection_policy +# Path on the source cluster for local or remote protection + source_dir: /example_view_path +# Path on the destination cluster for remote protection + target_exported_dir: /example_destination_path diff --git a/hosts b/hosts new file mode 100644 index 0000000..78ade8e --- /dev/null +++ b/hosts @@ -0,0 +1,4 @@ +[virtual_clusters] +### Replace with the name of your VAST Data Cluster, this is case-sensitive. +### If you are using an Ansible Host instead of locally installed Ansible software, please indicate the IP adress to that Anisble host. +sales-devvm-brett-dellandre ansible_host=127.0.0.1 diff --git a/initial.yml b/initial.yml new file mode 100644 index 0000000..cadcd67 --- /dev/null +++ b/initial.yml @@ -0,0 +1,10 @@ +- hosts: all + gather_facts: no + vars_files: + - secrets.yml + roles: + - {name: viewpolicies, tags: [setup-viewpolicies]} + - {name: views, tags: [setup-views]} + - {name: quotas, tags: [setup-quotas]} + - {name: protectionpolicies, tags: [setup-protectionpolicies]} + - {name: protectedpath, tags: [setup-protectedpath]} \ No newline at end of file diff --git a/roles/protectedpath/tasks/main.yml b/roles/protectedpath/tasks/main.yml new file mode 100644 index 0000000..43ecf57 --- /dev/null +++ b/roles/protectedpath/tasks/main.yml @@ -0,0 +1,76 @@ +--- +- name: Find ID of Protection Policy + ansible.builtin.uri: + url: 'https://{{ vms_ip }}/api/protectionpolicies/' + return_content: false + method: GET + user: "{{ vast_user }}" + password: "{{ vast_pass }}" + status_code: 200 + force_basic_auth: yes + validate_certs: false + body_format: json + delegate_to: localhost + register: protectpolicyfind + +- name: Set up Protected Path + ansible.builtin.uri: + url: 'https://{{ vms_ip }}/api/protectedpaths/' + return_content: true + method: "{{ item.method }}" + user: "{{ vast_user }}" + password: "{{ vast_pass }}" + status_code: 201, 200 + body: + name: "{{ item.name }}" + source_dir: "{{ item.source_dir }}" + protection_policy_id: "{{ protectpolicyfind.json | json_query(jmesquerypp) }}" + body_format: json + force_basic_auth: yes + validate_certs: false + delegate_to: localhost + when: item.method == "POST" + register: protectedpathcreate + ignore_errors: true + vars: + jmesquerypp: "[? name=='{{ item.protection_policy_name }}'].id | [0]" + changed_when: protectedpathcreate.status != 409 + failed_when: protectedpathcreate.status == 400 + loop: "{{ protectedpaths }}" + +- name: Find ID of Protected Path + ansible.builtin.uri: + url: 'https://{{ vms_ip }}/api/protectedpaths/' + return_content: false + method: GET + user: "{{ vast_user }}" + password: "{{ vast_pass }}" + status_code: 200 + force_basic_auth: yes + validate_certs: false + body_format: json + delegate_to: localhost + register: protectedpathfind + +- name: Edit Protected Path + ansible.builtin.uri: + url: 'https://{{ vms_ip }}/api/protectedpaths/{{ protectedpathfind.json | json_query(jmesquerypa) }}/' + return_content: true + method: "{{ item.method }}" + user: "{{ vast_user }}" + password: "{{ vast_pass }}" + status_code: 201, 200, 204 + body: + name: "{{ item.name }}" + body_format: json + force_basic_auth: yes + validate_certs: false + delegate_to: localhost + when: item.method != "POST" + register: protectedpathedit + ignore_errors: true + vars: + jmesquerypa: "[? name=='{{ item.name }}'].id | [0]" + changed_when: protectedpathedit.status != 409 + failed_when: protectedpathedit.status == 400 + loop: "{{ protectedpaths }}" diff --git a/roles/protectionpolicies/tasks/main.yml b/roles/protectionpolicies/tasks/main.yml new file mode 100644 index 0000000..704c3de --- /dev/null +++ b/roles/protectionpolicies/tasks/main.yml @@ -0,0 +1,91 @@ +--- +- name: Gather Time Facts + setup: + gather_subset: + - 'date_time' + delegate_to: localhost + +- name: Set up Protection Policies + ansible.builtin.uri: + url: 'https://{{ vms_ip }}/api/protectionpolicies/' + return_content: true + method: "{{ item.method }}" + user: "{{ vast_user }}" + password: "{{ vast_pass }}" + status_code: 201, 200 + body: + name: "{{ item.name }}" + frames: + - + every: "{{ item.every_value }}{{ item.every_unit }}" + every_value: "{{ item.every_value }}" + every_unit: "{{ item.every_unit }}" + start-at: "{{ ansible_date_time.date }} {{ ansible_date_time.time }}" + keep-local: "{{ item.keep_local_value }}{{ item.keep_local_period }}" + keep-remote: "{{ item.keep_remote | default(omit) }}" + local-period: "{{ item.keep_local_period }}" + prefix: "{{ item.snapshot_prefix }}" + clone_type: "{{ item.clone_type|upper }}" + target_object_id: "{{ item.replication_target | default(omit) }}" + indestructible: "{{ item.indestructible }}" + body_format: json + force_basic_auth: yes + validate_certs: false + delegate_to: localhost + when: item.method == "POST" + register: protectionpolicycreate + ignore_errors: true + changed_when: protectionpolicycreate.status != 409 + failed_when: protectionpolicycreate.status == 400 + loop: "{{ protectionpolicies }}" + +- name: Find ID of Protection Policy + block: + - name: Get ID of Protection Policy + ansible.builtin.uri: + url: 'https://{{ vms_ip }}/api/protectionpolicies/' + return_content: false + method: GET + user: "{{ vast_user }}" + password: "{{ vast_pass }}" + status_code: 200 + force_basic_auth: yes + validate_certs: false + body_format: json + delegate_to: localhost + register: protectionpolicyfind + +- name: Edit Protection Policies + ansible.builtin.uri: + url: 'https://{{ vms_ip }}/api/protectionpolicies/{{ protectionpolicyfind.json | json_query(jmesquerypp) }}/' + return_content: true + method: "{{ item.method }}" + user: "{{ vast_user }}" + password: "{{ vast_pass }}" + status_code: 201, 200 + body: + name: "{{ item.name }}" + frames: + - + every: "{{ item.every_value }}{{ item.every_unit }}" + every_value: "{{ item.every_value }}" + every_unit: "{{ item.every_unit }}" + keep-local: "{{ item.keep_local_value }}{{ item.keep_local_period }}" + keep-remote: "{{ item.keep_remote | default(omit) }}" + local-period: "{{ item.keep_local_period }}" + prefix: "{{ item.snapshot_prefix }}" + clone_type: "{{ item.clone_type|upper }}" + target_object_id: "{{ item.replication_target | default(omit) }}" + indestructible: "{{ item.indestructible }}" + body_format: json + force_basic_auth: yes + validate_certs: false + delegate_to: localhost + when: item.method != "POST" + register: protectionpolicyedit + ignore_errors: true + vars: + jmesquerypp: "[? name=='{{ item.name }}'].id | [0]" + changed_when: protectionpolicyedit.status != 409 + failed_when: protectionpolicyedit.status == 400 + loop: "{{ protectionpolicies }}" diff --git a/roles/quotas/tasks/main.yml b/roles/quotas/tasks/main.yml new file mode 100644 index 0000000..0ae90e2 --- /dev/null +++ b/roles/quotas/tasks/main.yml @@ -0,0 +1,79 @@ +--- +- name: Set up Quota + ansible.builtin.uri: + url: 'https://{{ vms_ip }}/api/quotas/' + return_content: true + method: "{{ item.method }}" + user: "{{ vast_user }}" + password: "{{ vast_pass }}" + status_code: 201, 200 + body: + name: "{{ item.name }}" + path: "{{ item.path }}" + soft_limit: "{{ item.soft_limit_capacity | human_to_bytes }}" + hard_limit: "{{ item.hard_limit_capacity | human_to_bytes }}" + soft_limit_inodes: "{{ item.soft_limit_folders }}" + hard_limit_inodes: "{{ item.hard_limit_folders }}" + enable_alarms: "{{ item.enable_alarms }}" + grace_period: "{{ item.grace_period }}" + enable_email_providers: "{{ item.enable_email_providers }}" + create_dir: "{{ item.create_dir }}" + is_user_quota: "{{ item.is_user_quota}}" + body_format: json + force_basic_auth: yes + validate_certs: false + delegate_to: localhost + when: item.method == "POST" + register: quotacreate + ignore_errors: true + changed_when: quotacreate.status != 409 + failed_when: quotacreate.status == 400 + loop: "{{ quotas }}" + +- name: Find ID of Quota Policy + block: + - name: Get ID of Quota Policy + ansible.builtin.uri: + url: 'https://{{ vms_ip }}/api/quotas/' + return_content: false + method: GET + user: "{{ vast_user }}" + password: "{{ vast_pass }}" + status_code: 200 + force_basic_auth: yes + validate_certs: false + body_format: json + delegate_to: localhost + register: quotasfind + +- name: Edit Quota + ansible.builtin.uri: + url: 'https://{{ vms_ip }}/api/quotas/{{ quotasfind.json | json_query(jmesqueryq) }}/' + return_content: true + method: "{{ item.method }}" + user: "{{ vast_user }}" + password: "{{ vast_pass }}" + status_code: 201, 200, 204 + body: + name: "{{ item.name }}" + path: "{{ item.path }}" + soft_limit: "{{ item.soft_limit_capacity | human_to_bytes }}" + hard_limit: "{{ item.hard_limit_capacity | human_to_bytes }}" + soft_limit_inodes: "{{ item.soft_limit_folders }}" + hard_limit_inodes: "{{ item.hard_limit_folders }}" + enable_alarms: "{{ item.enable_alarms }}" + grace_period: "{{ item.grace_period }}" + enable_email_providers: "{{ item.enable_email_providers }}" + create_dir: "{{ item.create_dir }}" + body_format: json + force_basic_auth: yes + validate_certs: false + delegate_to: localhost + when: item.method != "POST" + register: quotaedit + ignore_errors: true + vars: + jmesqueryq: "[? name=='{{ item.name }}'].id | [0]" + changed_when: quotaedit.status != 409 + failed_when: quotaedit.status == 400 + loop: "{{ quotas }}" diff --git a/roles/viewpolicies/tasks/main.yml b/roles/viewpolicies/tasks/main.yml new file mode 100644 index 0000000..f99614b --- /dev/null +++ b/roles/viewpolicies/tasks/main.yml @@ -0,0 +1,144 @@ +--- +- name: Find ID of VIP Pool + block: + - name: Get ID of VIP Pool + ansible.builtin.uri: + url: 'https://{{ vms_ip }}/api/vippools/' + return_content: false + method: GET + user: "{{ vast_user }}" + password: "{{ vast_pass }}" + status_code: 200 + force_basic_auth: yes + validate_certs: false + body_format: json + delegate_to: localhost + register: vippoolfind + +- name: Set up view policy + ansible.builtin.uri: + url: 'https://{{ vms_ip }}/api/viewpolicies/' + return_content: true + method: "{{ item.method }}" + user: "{{ vast_user }}" + password: "{{ vast_pass }}" + status_code: 201, 200 + body: + name: "{{ item.name }}" + flavor: "{{ item.flavor }}" + # vip_pools: ["{{ vippoolfind.json | json_query(jmesquery) }}"] + use_auth_provider: "{{ item.use_auth_provider | default(omit) }}" + nfs_posix_acl: "{{ item.nfs_posix_acl | default(omit) }}" + auth_source: "{{ item.auth_source }}" + path_length: "{{ item.path_length | default(omit) }}" + allowed_characters: "{{ item.allowed_characters | default(omit) }}" + nfs_no_squash: "{{ item.nfs_no_squash | default(omit) }}" + nfs_root_squash: "{{ item.nfs_root_squash | default(omit) }}" + nfs_all_squash: "{{ item.nfs_all_squash | default(omit) }}" + trash_access: "{{ item.trash_access | default(omit) }}" + read_write: "{{ item.nfs_read_write | default(omit) }}" + read_only: "{{ item.nfs_read_only | default(omit) }}" + smb_read_write: "{{ item.smb_read_write | default(omit) }}" + smb_read_only: "{{ item.smb_read_only | default(omit) }}" + s3_read_write: "{{ item.s3_read_write | default(omit) }}" + s3_read_only: "{{ item.s3_read_only | default(omit) }}" + s3_visibility: "{{ item.s3_visibility | default(omit) }}" + s3_visibility_groups: "{{ item.s3_visibility_groups | default(omit) }}" + apple_sid: "{{ item.apple_sid | default(omit) }}" + body_format: json + force_basic_auth: yes + validate_certs: false + delegate_to: localhost + when: item.method == "POST" + register: viewpolicycreate + ignore_errors: true + # vars: + # jmesquery: "[? name=='{{ item.vip_pool_name }}'].id | [0] || []]" + changed_when: viewpolicycreate.status != 409 + failed_when: viewpolicycreate.status == 400 + loop: "{{ viewpolicies }}" + +- name: Find ID of View Policy + block: + - name: Get ID of View Policy + ansible.builtin.uri: + url: 'https://{{ vms_ip }}/api/viewpolicies/' + return_content: false + method: GET + user: "{{ vast_user }}" + password: "{{ vast_pass }}" + status_code: 200 + force_basic_auth: yes + validate_certs: false + body_format: json + delegate_to: localhost + register: viewpolicyfind + +- name: Edit viewpolicy with VIPPOOL + ansible.builtin.uri: + url: 'https://{{ vms_ip }}/api/viewpolicies/{{ viewpolicyfind.json | json_query(jmesqueryvp) }}/' + return_content: true + method: "PATCH" + user: "{{ vast_user }}" + password: "{{ vast_pass }}" + status_code: 200, 201, 203, 204, 301 + body: + vip_pools: ["{{ vippoolfind.json | json_query(jmesquery) }}"] + body_format: json + force_basic_auth: yes + validate_certs: false + delegate_to: localhost + # when: item.vip_pool_name | length == 1 and item.method == "POST" + register: viewpolicycreatevip + ignore_errors: true + vars: + jmesquery: "[? name=='{{ item.vip_pool_name }}'].id | [0]" + jmesqueryvp: "[? name=='{{ item.name }}'].id | [0]" + changed_when: viewpolicycreatevip.status != 409 + failed_when: viewpolicycreatevip.status == 400 + when: item.vip_pool_name is defined and item.vip_pool_name != '' and item.method == 'POST' + loop: "{{ viewpolicies }}" + +- name: Edit viewpolicy + ansible.builtin.uri: + url: 'https://{{ vms_ip }}/api/viewpolicies/{{ viewpolicyfind.json | json_query(jmesqueryvp) }}/' + return_content: true + method: "{{ item.method }}" + user: "{{ vast_user }}" + password: "{{ vast_pass }}" + status_code: 200, 201, 203, 204, 301 + body: + name: "{{ item.name }}" + flavor: "{{ item.flavor }}" + # vip_pools: ["{{ vippoolfind.json | json_query(jmesquery) }}"] + use_auth_provider: "{{ item.use_auth_provider | default(omit) }}" + nfs_posix_acl: "{{ item.nfs_posix_acl | default(omit) }}" + auth_source: "{{ item.auth_source }}" + path_length: "{{ item.path_length | default(omit) }}" + allowed_characters: "{{ item.allowed_characters | default(omit) }}" + nfs_no_squash: "{{ item.nfs_no_squash | default(omit) }}" + nfs_root_squash: "{{ item.nfs_root_squash | default(omit) }}" + nfs_all_squash: "{{ item.nfs_all_squash | default(omit) }}" + trash_access: "{{ item.trash_access | default(omit) }}" + read_write: "{{ item.nfs_read_write | default(omit) }}" + read_only: "{{ item.nfs_read_only | default(omit) }}" + smb_read_write: "{{ item.smb_read_write | default(omit) }}" + smb_read_only: "{{ item.smb_read_only | default(omit) }}" + s3_read_write: "{{ item.s3_read_write | default(omit) }}" + s3_read_only: "{{ item.s3_read_only | default(omit) }}" + s3_visibility: "{{ item.s3_visibility | default(omit) }}" + s3_visibility_groups: "{{ item.s3_visibility_groups | default(omit) }}" + apple_sid: "{{ item.apple_sid | default(omit) }}" + body_format: json + force_basic_auth: yes + validate_certs: false + delegate_to: localhost + when: item.method != "POST" + register: viewpolicyedit + ignore_errors: true + vars: + # jmesquery: "[? name=='{{ item.vip_pool_name }}'].id | [0]" + jmesqueryvp: "[? name=='{{ item.name }}'].id | [0]" + changed_when: viewpolicyedit.status != 409 + failed_when: viewpolicyedit.status == 400 + loop: "{{ viewpolicies }}" diff --git a/roles/views/tasks/main.yml b/roles/views/tasks/main.yml new file mode 100644 index 0000000..56e8859 --- /dev/null +++ b/roles/views/tasks/main.yml @@ -0,0 +1,89 @@ +--- +- name: Find ID of View Policy + block: + - name: Find ID of View Policy + ansible.builtin.uri: + url: 'https://{{ vms_ip }}/api/viewpolicies/' + return_content: false + method: GET + user: "{{ vast_user }}" + password: "{{ vast_pass }}" + status_code: 200 + force_basic_auth: yes + validate_certs: false + body_format: json + delegate_to: localhost + register: viewpolicyfind + +- name: Set up views + ansible.builtin.uri: + url: 'https://{{ vms_ip }}/api/views/' + return_content: true + method: "{{ item.method }}" + user: "{{ vast_user }}" + password: "{{ vast_pass }}" + status_code: 201, 200 + body: + path: "{{ item.path }}" + policy_id: "{{ viewpolicyfind.json | json_query(jmesquery) }}" + alias: "{{ item.alias | default(omit) }}" + protocols: "{{ item.protocols.split(',') }}" + create_dir: "{{ item.create_dir }}" + share: "{{ item.share | default(omit) }}" + body_format: json + force_basic_auth: yes + validate_certs: false + delegate_to: localhost + when: item.method == "POST" + register: viewscreate + ignore_errors: true + vars: + jmesquery: "[? name=='{{ item.view_policy_name }}'].id | [0]" + changed_when: viewscreate.status != 409 + failed_when: viewscreate.status == 400 + loop: "{{ views }}" + +- name: Find ID of View + block: + - name: Get ID of View + ansible.builtin.uri: + url: 'https://{{ vms_ip }}/api/views/' + return_content: false + method: GET + user: "{{ vast_user }}" + password: "{{ vast_pass }}" + status_code: 200 + force_basic_auth: yes + validate_certs: false + body_format: json + delegate_to: localhost + register: viewfind + +- name: Edit views + ansible.builtin.uri: + url: 'https://{{ vms_ip }}/api/views/{{ viewfind.json | json_query(jmesquery) }}/' + return_content: true + method: "{{ item.method }}" + user: "{{ vast_user }}" + password: "{{ vast_pass }}" + status_code: 200, 201, 203, 204, 301 + body: + path: "{{ item.path }}" + policy_id: ["{{ viewpolicyfind.json | json_query(jmesqueryvp) }}"] + alias: "{{ item.alias | default(omit) }}" + protocols: "{{ item.protocols.split(',') }}" + create_dir: "{{ item.create_dir }}" + share: "{{ item.share | default(omit) }}" + body_format: json + force_basic_auth: yes + validate_certs: false + delegate_to: localhost + when: item.method != "POST" + register: viewsedit + ignore_errors: true + vars: + jmesquery: "[? path=='{{ item.path }}'].id | [0]" + jmesqueryvp: "[? name=='{{ item.view_policy_name }}'].id | [0]" + changed_when: viewsedit.status != 409 + failed_when: viewsedit.status == 400 + loop: "{{ views }}" diff --git a/secrets.yml b/secrets.yml new file mode 100644 index 0000000..af736ab --- /dev/null +++ b/secrets.yml @@ -0,0 +1,7 @@ +$ANSIBLE_VAULT;1.1;AES256 +64326239663361376530373132336430306532393135353933356434343066666365643435323230 +3164656136633430383562643537376530373161383166330a393939366166393236316435656438 +64623337653432313136316232356362343061303862353965666633646634383666626431363836 +3536623066663763320a646463363566303935326535376165653963383566393562616238343266 +61626663346636303061633064393436383731663862303966653931643533386137626463656233 +3764613832646663633163353931353735623539653935643130