From 86e3cca702a35338d0a5526d25024ace8fad5385 Mon Sep 17 00:00:00 2001 From: Nathan Melehan Date: Tue, 17 Sep 2024 10:55:51 -0400 Subject: [PATCH 1/6] Fix description for Alex Fornuto contributor page (#7096) * Fix description for Alex Fornuto contributor page * Update docs/contributors/alex-fornuto/_index.md Co-authored-by: Alex Fornuto --------- Co-authored-by: Rajakavitha Kodhandapani Co-authored-by: Alex Fornuto --- docs/contributors/alex-fornuto/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contributors/alex-fornuto/_index.md b/docs/contributors/alex-fornuto/_index.md index b8e25278aab..744b51724c9 100644 --- a/docs/contributors/alex-fornuto/_index.md +++ b/docs/contributors/alex-fornuto/_index.md @@ -5,4 +5,4 @@ email: "" description: "The Linode documentation library's profile page and submission listing for Alex Fornuto" --- -Alex Fornuto is an independent contributor to the Linode documentation library. Their submissions can be found listed below. \ No newline at end of file +Alex Fornuto is a former Linode employee and documentation team lead. Their submissions can be found listed below. \ No newline at end of file From 6b0aa23516b0fb84767af20afa30ce93ca2a5d49 Mon Sep 17 00:00:00 2001 From: Adam Overa Date: Tue, 17 Sep 2024 11:50:13 -0400 Subject: [PATCH 2/6] [NEW] One Dozen Ansible Security Benefits (#7075) * One Dozen Ansible Security Benefits * Tech Edit 1 * Tech Edit 2 * copy edits, retitle, reformatting --------- Co-authored-by: John Dutton --- ci/vale/dictionary.txt | 1 + .../ansible-security-benefits/index.md | 115 ++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 docs/guides/applications/configuration-management/ansible/ansible-security-benefits/index.md diff --git a/ci/vale/dictionary.txt b/ci/vale/dictionary.txt index a22e22704d1..c1b9a0b15bb 100644 --- a/ci/vale/dictionary.txt +++ b/ci/vale/dictionary.txt @@ -1035,6 +1035,7 @@ icingacli icmp icmpv6 idempotence +idempotency ident identrust iDimensionz diff --git a/docs/guides/applications/configuration-management/ansible/ansible-security-benefits/index.md b/docs/guides/applications/configuration-management/ansible/ansible-security-benefits/index.md new file mode 100644 index 00000000000..74b755f15fe --- /dev/null +++ b/docs/guides/applications/configuration-management/ansible/ansible-security-benefits/index.md @@ -0,0 +1,115 @@ +--- +slug: ansible-security-benefits +title: "11 Ansible Security Benefits" +description: "This guide discusses how Ansible can enhance security through efficient patching, RBAC, and secure secrets handling for reliable IT management." +authors: ["Cameron Laird"] +contributors: ["Cameron Laird"] +published: 2024-08-06 +keywords: ['ansible security practices','ansible security patching','agentless architecture','secrets management'] +license: '[CC BY-ND 4.0](https://creativecommons.org/licenses/by-nd/4.0)' +external_resources: +- '[Ansible Collaborative Official Site](https://www.ansible.com/)' +--- + +[Ansible](/docs/guides/applications/configuration-management/ansible/) is an automation engine used for enabling infrastructure as code (IaC), managing and deploying applications, and automating processes. It is often considered a tool for system administrators, DevOps practitioners, and related IT specialists. + +Ansible workflows have significant implications for IT security, both enhancing it and introducing potential risks. This guide discusses various security benefits and considerations of using Ansible. + +## Source Control Integration + +Ansible's configuration management capabilities enable various security techniques associated with effective [infrastructure as code](/docs/guides/introduction-to-infrastructure-as-code/), including: + +- **Versioning and Change Tracking**: Keeps a detailed record of what changes are made, when, and by whom. +- **Auditing and Compliance**: Ensures changes to sensitive documents are made, reviewed, and approved by authorized personnel. +- **Consistent and Sustainable RBAC**: Links access, actions, and accountability, ensuring that only authorized users can make specific changes. +- **Disaster Recovery and Rollback**: Facilitates recovery from failures by rolling back to a stable state. +- **Peer Review**: Manages concurrent collaboration through the source control system. Multiple teams can work on different aspects of an Ansible configuration simultaneously, with the system detecting conflicts before they cause issues. + +The integration of these techniques together allows you to use the same Single Sign On (SSO) passwords, development lifecycles, and permission schemes for Ansible authentication as you do for other workflows. Consistent use of IaC can prevent defects, ensuring the resulting operations are both predictable and secure. + +## Secure Communication + +Ansible uses `ssh` as its default transport protocol. In addition to accessing `ssh` through standard clients and servers, Ansible also uses [Paramiko](https://www.paramiko.org/), a [Python](/docs/guides/development/python/) implementation of [OpenSSH](https://www.openssh.com/). These components are regarded as secure for commercial traffic. + +Ansible encrypts all communications, and authentication mechanisms include public-key, password, and [Kerberos](https://www.techtarget.com/searchsecurity/definition/Kerberos) protocol. + +## Idempotent Operations + +Ansible emphasizes declarative and [idempotent](https://dev.to/admantium/ansible-idempotent-playbooks-4e67) actions (i.e. actions that are defined by their goals). An idempotent action is considered safe to repeat or replay, because it only performs what is necessary to achieve the intended goal. Ansible's declarative playbooks help prevent different operators from interpreting instructions in different ways. + +Consistency is achieved when all individual assets that share the same target reach the same state. This applies to both new and old assets. When a manual action leads to an inconsistent state, another idempotent invocation can bring any deviant systems back in line. Idempotence helps limit human errors and unnecessary changes, promotes consistent system states, and supports transparent auditing and troubleshooting. + +## Role-based Access Control + +Ansible supports role-based access control ([RBAC](https://auth0.com/docs/manage-users/access-control/rbac)), assigning permissions based on a user's responsibilities and authority. RBAC enhances security by providing granular access to assets. This granularity helps in modelling [least privilege](https://www.beyondtrust.com/blog/entry/what-is-least-privilege) or minimal privilege configurations. + +Ansible supports RBAC at two levels: + +- **Ansible Core:** The [community release](https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html) of Ansible relies on operating system (OS) mechanisms for authentication and authorization, and therefore supports RBAC as well as the underlying OS. + +- **Ansible Tower:** The [Ansible Tower](https://www.redhat.com/sysadmin/intro-ansible-tower) enterprise-class version of [Ansible fully implements and supports RBAC](https://docs.ansible.com/ansible-tower/latest/html/userguide/security.html). + +## Secrets Management Through Vaults + +Secure systems rely on "secrets", that is, information restricted to those with a need-to-know. [Ansible Vault](https://docs.ansible.com/ansible/latest/vault_guide/index.html) is a feature of Ansible that protects various kinds of secret information in encrypted files, including database passwords, documents with sensitive contents, and private keys. + +Ansible Vault addresses common challenges related to secrets management: + +- Ansible users do not need to generate their own schemes for protecting secrets. + +- Its file encryption eliminates the need to store sensitive information in plaintext files. + +- Ansible Vault manages access to secrets so the risk of them leaking beyond their intended recipients is minimized. + +## Audit Logging + +Ansible's audit logging records the details of playbook execution, such as tasks performed, changes effected, and events observed. There are both benefits and risk factors related to audit logging and security. + +Audit logs can be valuable for forensic analysis and review, helping operators gain understanding into what occurs on a system. They also must be secured and protected since they have the potential to expose sensitive information like credentials and system configurations. Specifically, that protection should restrict *read* access to only those with a need-to-know their contents. Safeguarding audit log *write* access can also help prevent unauthorized modifications or tampering of logs. + +Like other business continuity measures, audit logs typically receive attention during a crisis. This means their verification and practice needs to happen before the time of their use. Familiarity with audit logs deserves routine drills so that the logs are accurate and dependable when they are needed. + +To be both useful and adequately secure, audit logs must be highly available, securely backed up, regularly monitored, periodically reviewed, and protected by granular RBAC. When appropriate, audit logs should be integrated with Security Information and Event Management (SIEM) systems. They must also comply with pertinent legal requirements like GDPR or HIPAA. + +## Continuous Compliance Checking + +Ansible features compliance automation, real-time monitoring, auditing, and accountability to ensure systems are in optimal health and continuously supervised. It protects systems using multiple layers of security mechanisms that make sure configurations are performing as intended. By automating compliance tasks, results are more consistent, the need for manual intervention is reduced, and dependence on subject matter experts is minimized. + +## Security Patching + +Security patching with Ansible is governed by Ansible's authentication and accountability mechanisms to enhance the efficiency and effectiveness of the patching process. Ansible playbooks verify patch application and ensure consistent, secure, and transparent results. + +The consistency of Ansible's security mechanisms also enable concurrent development and patching to help efficiently resolve crises. When multiple patches must be managed simultaneously, Ansible's IaC model allows different teams to prepare and test their patches at the same time without hindering each other's progress. + +## Custom Modules + +Security work often emphasizes the use of well-known, proven techniques. However, many real-world computing systems likely require some customization to meet specific needs. Ansible's custom modules allow for customization by extending its base functionality in a predictable and manageable way. With that in mind, there are potential risks that come with using custom modules: + +- **Malicious or Erroneous Code Execution**: Custom modules can execute arbitrary code from the Ansible control node. Breakdowns can lead to data breaches, unauthorized system access, or service disruption. +- **Escalated Privileges**: Custom modules have the ability to edit permissions. Unauthorized users or users with lower privileges could exploit custom modules to perform actions they otherwise wouldn't be able to do. +- **Exposed Information**: Passwords, API keys, and security tokens frequently appear in custom modules. +- **Insecure Input Handling**: Custom modules often receive user inputs. It is crucial to sanitize these inputs to eliminate injection vulnerabilities. +- **Lack of Proper Authentication and Authorization**: Custom modules can be misused to act beyond their original intent. +- **Compromised Code Integrity**: Custom modules require thorough review before being deployed to ensure they don't compromise the system. + +Custom modules can be useful, but they require ongoing support. Even if modules are functioning well and remain unchanged, it is a best practice to give them periodic review to ensure they remain unaffected by security advisories and meet security standards. + +## Consistency in Multi-tier Environments + +Ansible can be useful for managing configurations across development, testing, staging, and production environments. Consistent management across tiers is important, and there are numerous security considerations that come with multi-tier environments: + +- Secure private information to prevent exposure in plaintext playbooks. This is often done with Ansible Vault. + +- Network segmentation should isolate and secure hosts to prevent unauthorized access from the Ansible control machine. + +- To ensure accountability and restricted access, credentials and privileges should adhere to RBAC principles. + +- Auditing and logging should record tier-specific information to identify and isolate suspicious activity as quickly as possible. + +## Community and Vendor Support + +Some of Ansible's strengths are the extensive community and vendor support options available. These include Ansible's documentation library and community forums, along with the wealth of shared content and knowledge provided by other users. As a best practice, community resources generally deserve review before implementing them in your environment: + +- [Ansible community documentation](https://docs.ansible.com/) + +- [Ansible community forums](https://forum.ansible.com/?extIdCarryOver=true&sc_cid=701f2000001OH7YAAW) \ No newline at end of file From 9cb243277dc1acb6e6ef0e77d963f73f3f392154 Mon Sep 17 00:00:00 2001 From: Rajakavitha Kodhandapani Date: Tue, 17 Sep 2024 21:20:25 +0530 Subject: [PATCH 3/6] [Update] Securing phpMyAdmin (#7070) Set the value of cfg['RestrictPaths'] to true because the value is boolean as described in the official documentation: docs.phpmyadmin.net/en/latest/config.html#cookie-authetication-options --- docs/guides/security/basics/how-to-secure-phpmyadmin/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guides/security/basics/how-to-secure-phpmyadmin/index.md b/docs/guides/security/basics/how-to-secure-phpmyadmin/index.md index a112b3853dc..6a60caf77cb 100644 --- a/docs/guides/security/basics/how-to-secure-phpmyadmin/index.md +++ b/docs/guides/security/basics/how-to-secure-phpmyadmin/index.md @@ -279,7 +279,7 @@ $cfg['LoginCookieValidity'] = 14400; $cfg['LoginCookieRecall'] = false; $cfg['AllowUserDropDatabase'] = false; $cfg['ShowServerInfo'] = false; -$cfg['RestrictPaths'] = yes; +$cfg['RestrictPaths'] = true; {{< /file >}} These configuration options will change the default cookie validity time, automatically logging users out after a predefined period of time. It will also prevent users from deleting databases and will omit server information from phpMyAdmin. From 5b5f27d24d575fd2abbbd623102b6c17c1f4a5c0 Mon Sep 17 00:00:00 2001 From: 21CSM <81891917+21CSM@users.noreply.github.com> Date: Tue, 17 Sep 2024 11:50:35 -0400 Subject: [PATCH 4/6] Fix outdated information on the NixOS guide (#7033) This change modifies the guide to increase the default installer disk size from 1024 MB to 1280 MB, due to latest NixOS minimal ISO size being over 1024 MB --- .../custom-kernels-distros/install-nixos-on-linode/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/guides/tools-reference/custom-kernels-distros/install-nixos-on-linode/index.md b/docs/guides/tools-reference/custom-kernels-distros/install-nixos-on-linode/index.md index 25ced7862c9..1f2f544d59a 100644 --- a/docs/guides/tools-reference/custom-kernels-distros/install-nixos-on-linode/index.md +++ b/docs/guides/tools-reference/custom-kernels-distros/install-nixos-on-linode/index.md @@ -5,7 +5,7 @@ description: 'Install NixOS, which is known for its declarative approach to conf authors: ["Andrew Miller"] contributors: ["Andrew Miller"] published: 2017-06-16 -modified: 2023-07-11 +modified: 2024-07-05 keywords: ["custom distro", "NixOS", "advanced Linux", "kvm"] tags: ["cloud manager"] license: '[CC BY-ND 4.0](https://creativecommons.org/licenses/by-nd/4.0)' @@ -48,7 +48,7 @@ To create a new Linode, go to the [Create Linode page](https://cloud.linode.com/ [Create three disk images](/docs/products/compute/compute-instances/guides/disks-and-storage/#create-a-disk): One for the installer, one for a swap partition, and one for the root partition. Label them: -- **Installer**: A type `ext4` disk, 1024 MB in size. +- **Installer**: A type `ext4` disk, 1280 MB in size. - **Swap**: A `swap` disk no larger than 512 MB. - **NixOS**: A type `ext4` disk which takes up all remaining space. @@ -340,4 +340,4 @@ After installation, Longview can be set up for your NixOS instance. echo $longview_key > /var/lib/longview/apiKeyFile | sudo tee /var/lib/longview/apiKeyFile ``` - Replace the value of `longview_key` above with the one you got from [Longview](https://cloud.linode.com/longview/clients). \ No newline at end of file + Replace the value of `longview_key` above with the one you got from [Longview](https://cloud.linode.com/longview/clients). From d37c65da030dda01cd4febaebe408593773103c7 Mon Sep 17 00:00:00 2001 From: Joseph Cardillo Date: Tue, 17 Sep 2024 13:49:31 -0400 Subject: [PATCH 5/6] Apache Spark One Click Cluster Marketplace Guide (#7092) * Initial draft of Apache Spark Cluster marketplace guide * review * added spark-cluster.png file * copy edit --------- Co-authored-by: Anna Bracha Co-authored-by: John Dutton --- .../guides/apache-spark-cluster/index.md | 87 ++++++++++++++++++ .../apache-spark-cluster/spark-cluster.png | Bin 0 -> 53528 bytes 2 files changed, 87 insertions(+) create mode 100644 docs/marketplace-docs/guides/apache-spark-cluster/index.md create mode 100644 docs/marketplace-docs/guides/apache-spark-cluster/spark-cluster.png diff --git a/docs/marketplace-docs/guides/apache-spark-cluster/index.md b/docs/marketplace-docs/guides/apache-spark-cluster/index.md new file mode 100644 index 00000000000..00474ed8fda --- /dev/null +++ b/docs/marketplace-docs/guides/apache-spark-cluster/index.md @@ -0,0 +1,87 @@ +--- +title: "Deploy Apache Spark through the Linode Marketplace" +description: "Apache Spark is a powerful open-source unified analytics engine for large-scale data processing. It provides high-level APIs in Java, Scala, Python, and R, and an optimized engine that supports general execution graphs. Spark is designed for both batch and streaming data processing, and it's significantly faster than traditional big data processing frameworks." +published: 2024-07-09 +modified: 2024-07-09 +keywords: ['spark','apache spark', 'marketplace', 'bigdata','analytics'] +tags: ["ubuntu","marketplace", "big data", "linode platform", "cloud manager", "analytics", "cloud storage", "high availability", "compute storage"] +external_resources: +- '[About Apache Spark](https://spark.apache.org/)' +- '[Apache Spark Documentation](https://spark.apache.org/docs/latest/)' +--- + +[Apache Spark](https://spark.apache.org/) is a powerful open-source unified analytics engine for large-scale data processing. It provides high-level APIs in Java, Scala, Python, and R, and an optimized engine that supports general execution graphs. Spark is designed for both batch and streaming data processing, and it's significantly faster than traditional big data processing frameworks. + +This cluster is deployed with Apache Spark in standalone cluster mode and consists of a master node along with two worker nodes. The standalone cluster manager is a simple way to run Spark in a distributed environment, providing easy setup and management for Spark applications. + +Scala, a multi-paradigm programming language, is integral to Apache Spark. It combines object-oriented and functional programming in a concise, high-level language that runs on the Java Virtual Machine (JVM). Spark itself is written in Scala, and while Spark supports multiple languages, Scala provides the most natural and performant interface to Spark's APIs. + +NGINX is installed on the master node as a reverse proxy to the worker nodes. The user interface URL is the domain (or rDNS value if no domain was entered). The workers are available via this reverse proxy setup. To access the UI on the master, you will need to provide the username and password that are specified during the cluster deployment. These credentials are also available at `/home/$USER/.credentials` for reference. + +A Let's Encrypt Certificate is installed in the NGINX configuration. Using NGINX as a reverse proxy allows for both authentication to the front-end UI and a simple means for renewing the Let's Encrypt certificates for HTTPS. + +The minimum RAM requirement for the worker nodes is 4GB RAM to ensure that jobs can run on the workers without encountering memory constraints. This configuration allows for efficient processing of moderately sized datasets and complex analytics tasks. + +## Cluster Deployment Architecture + +![Spark Architecture](spark-cluster.png) + +## Deploying a Marketplace App + +{{% content "deploy-marketplace-apps-shortguide" %}} + +{{% content "marketplace-verify-standard-shortguide" %}} + +{{< note >}} +**Estimated deployment time:** Your Spark cluster should be fully installed within 5-7 minutes after the Compute Instance has finished provisioning. +{{< /note >}} + +## Configuration Options + +- **Supported distributions:** Ubuntu 22.04 LTS +- **Suggested minimum plan:** 4GB RAM + +### Spark Options + +- **[Linode API Token](/docs/products/tools/api/guides/manage-api-tokens/#create-an-api-token):** The provisioner node uses an authenticated API token to create the additional components to the cluster. This is required to fully create the Spark cluster. + +{{% content "marketplace-required-limited-user-fields-shortguide" %}} + +- **Spark cluster size:** The size of the Spark cluster. This cluster is deployed with a master node and two worker nodes. + +- **Spark user:** The username you wish to use to log in to the Spark UI. + +- **Spark UI password:** The password you wish to use to log in to the Spark UI. + +{{% content "marketplace-special-character-limitations-shortguide" %}} + +## Getting Started After Deployment + +### Spark UI + +Once the deployment is complete, visit the Spark UI at the URL provided at `/etc/motd`. This is either the domain you entered when deploying the cluster or the reverse DNS value of the master node. + +The Spark Cluster needs access to external storage such as S3, HDFS, Azure Blob Storage, Apache HBase, or your local filesystem. For more details on this, see [Integration With Cloud Infrastructures](https://spark.apache.org/docs/3.5.1/cloud-integration.html). + +### Authentication + +The credentials to log in to the Spark UI can be found in the home directory of the sudo user created on deployment: `/home/$SUDO_USER/.credentials`. For example, if you created a user called `{{< placeholder "admin" >}}`, the credentials file will be found in `/home/{{< placeholder "admin" >}}/.credentials`. + +### Spark Shell + +The `spark-shell` is included with the installation. The `spark-shell` is an interactive command-line shell provided by Apache Spark that allows you to interact with and perform data queries on a Spark cluster in real-time. + +## Software Included + +The Apache Spark Marketplace App installs the following software on your Linode: + +| **Software** | **Version** | **Description** | +| :--- | :---- | :--- | +| **Apache Spark** | 3.4 | Unified analytics engine for large-scale data processing | +| **Java OpenJDK** | 11.0 | Runtime environment for Spark | +| **Scala** | 2.11 | Programming language that Spark is built with, providing a powerful interface to Spark's APIs | +| **NGINX** | 1.18 | High-performance HTTP server and reverse proxy | +| **UFW** | | Uncomplicated Firewall for managing firewall rules | +| **Fail2ban** | | Intrusion prevention software framework for protection against brute-force attacks | + +{{% content "marketplace-update-note-shortguide" %}} \ No newline at end of file diff --git a/docs/marketplace-docs/guides/apache-spark-cluster/spark-cluster.png b/docs/marketplace-docs/guides/apache-spark-cluster/spark-cluster.png new file mode 100644 index 0000000000000000000000000000000000000000..b5b3b49597b136dc5f74786986f8641d307eebf4 GIT binary patch literal 53528 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

TV^>3 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 literal 0 HcmV?d00001 From 29d348e6a0a08e078b90906f13d349513849946c Mon Sep 17 00:00:00 2001 From: Nathan Melehan Date: Tue, 17 Sep 2024 15:09:59 -0400 Subject: [PATCH 6/6] Update theme (#7101) * Update theme - Reorganize home page - Reorder explore docs menu - Introduce card styling options for links - Add border around all section page items * Update nvmrc to fix Netlify preview * Revert "Update nvmrc to fix Netlify preview" This reverts commit 23f683ba7a8c6fb992f859b8c636ac27eb616fdd. --- .../assets/js/main/sections/home/home.js | 2 +- .../linode/linode-docs-theme/config.toml | 16 +- .../content/headless/home/data_v2.toml | 11 ++ .../content/testpages/links.md | 15 ++ .../layouts/_default/_markup/render-link.html | 130 +++++++++----- .../layouts/_default/list.html | 5 +- .../linode-docs-theme/layouts/index.html | 160 +++++++++--------- _vendor/modules.txt | 2 +- go.mod | 2 +- go.sum | 2 + 10 files changed, 210 insertions(+), 135 deletions(-) create mode 100644 _vendor/github.com/linode/linode-docs-theme/content/headless/home/data_v2.toml diff --git a/_vendor/github.com/linode/linode-docs-theme/assets/js/main/sections/home/home.js b/_vendor/github.com/linode/linode-docs-theme/assets/js/main/sections/home/home.js index 6a02603de65..8c17b6d3526 100644 --- a/_vendor/github.com/linode/linode-docs-theme/assets/js/main/sections/home/home.js +++ b/_vendor/github.com/linode/linode-docs-theme/assets/js/main/sections/home/home.js @@ -16,7 +16,7 @@ export function newHomeController(searchConfig, staticData) { // The section we paginate on the home page. // This maps to section.lvl0 in linode-merged. - const sectionLevel0s = ['guides', 'blog', 'resources', 'marketplace-docs']; + const sectionLevel0s = ['blog', 'resources']; // Avoid loading too much data when on mobile. const tilesAlgoliaPreloadItems = isMobile() ? 12 : 30; diff --git a/_vendor/github.com/linode/linode-docs-theme/config.toml b/_vendor/github.com/linode/linode-docs-theme/config.toml index 45e0cea7e2f..4567feb974b 100644 --- a/_vendor/github.com/linode/linode-docs-theme/config.toml +++ b/_vendor/github.com/linode/linode-docs-theme/config.toml @@ -51,7 +51,7 @@ filtering_facets = [ [params.search_config2.sections] [params.search_config2.sections.products] name = "products" -weight = 10 # Used to order the sections in the UI. Higher comes first. +weight = 35 # Used to order the sections in the UI. Higher comes first. title = "Products" noun = "Product Guide" static_link_url = "https://techdocs.akamai.com/cloud-computing/docs/" @@ -62,7 +62,7 @@ explorer_icon = "#icon-explorer--products" [params.search_config2.sections.guides] name = "guides" filters = "section.lvl0:guides" -weight = 20 +weight = 10 title = "Cloud Guides & Tutorials" noun = "Guide" explorer_icon = "#icon-explorer--guides" @@ -72,21 +72,21 @@ name = "api" index = "linode-documentation-api" static_link_url = "https://techdocs.akamai.com/linode-api/reference/api" filters = "section.lvl0:api" -weight = 30 +weight = 40 title = "API" explorer_icon = "#icon-explorer--api" [params.search_config2.sections.reference-architecture] name = "reference-architecture" filters = "section.lvl0:guides" -weight = 35 -title = "Reference Architecture" +weight = 20 +title = "Reference Architectures" noun = "Reference" explorer_icon = "#icon-explorer--reference-architecture" [params.search_config2.sections.marketplace-docs] name = "marketplace-docs" -weight = 40 +weight = 25 title = "Marketplace Docs" noun = "Marketplace" filters = "section.lvl0:marketplace-docs" @@ -107,8 +107,8 @@ static_link_url = "https://www.linode.com/blog/" name = "resources" filters = "section.lvl0:Resources" weight = 60 -title = "Resources" -noun = "Resource" +title = "Content Resources" +noun = "Content Resource" seo_title_template = "Cloud Computing Resources | Linode" seo_title_template_category = "Cloud Computing {category} | Linode" explorer_icon = "#icon-explorer--resources" diff --git a/_vendor/github.com/linode/linode-docs-theme/content/headless/home/data_v2.toml b/_vendor/github.com/linode/linode-docs-theme/content/headless/home/data_v2.toml new file mode 100644 index 00000000000..0d45308494c --- /dev/null +++ b/_vendor/github.com/linode/linode-docs-theme/content/headless/home/data_v2.toml @@ -0,0 +1,11 @@ +hero_text = "Developer resources for building on Akamai Connected Cloud" + +# Ordered list of section to display cards with the last 3 articles. +cards_sections = ["guides", "reference-architecture", "marketplace-docs"] + +[cards_now_on_tech_docs] + title = "Now on Akamai TechDocs" + cards = [ + { title = "Product docs", href = "https://techdocs.akamai.com/cloud-computing/docs/" }, + { title = "Linode API reference", href = "https://techdocs.akamai.com/linode-api/reference/api" }, + ] diff --git a/_vendor/github.com/linode/linode-docs-theme/content/testpages/links.md b/_vendor/github.com/linode/linode-docs-theme/content/testpages/links.md index 9f5b8156e45..7d91aa9a1fd 100644 --- a/_vendor/github.com/linode/linode-docs-theme/content/testpages/links.md +++ b/_vendor/github.com/linode/linode-docs-theme/content/testpages/links.md @@ -3,6 +3,21 @@ title: Testing Links description: This is a test page used in both manual and automatic tests. Do not delete. It will not be listed anywhere. --- +## Cool Links + +### With Markdown text and title set + +[Reprehenderit esse quis occaecat adipisicing aliquip. Dolor veniam **cupidatat cillum nulla** reprehenderit incididunt dolor in elit adipisicing. Sint incididunt non irure magna ipsum amet nulla aliqua nostrud laboris pariatur cillum eiusmod magna.](/docs/products/compute/kubernetes/guides/kubectl/?cardstyling "Link to Kubectl") + + +[Just a test link with additional params.](/docs/products/compute/kubernetes/guides/kubectl/?foo=bar&cardstyling "Link to Kubectl") + + +### Without Markdown text and title + +[](/docs/products/compute/kubernetes/guides/kubectl/?cardstyling) + +[](/docs/guides/preparing-infrastructure-for-high-impact-ad-traffic/?cardstyling) ## Links to Anchor Links diff --git a/_vendor/github.com/linode/linode-docs-theme/layouts/_default/_markup/render-link.html b/_vendor/github.com/linode/linode-docs-theme/layouts/_default/_markup/render-link.html index 431a7f220af..2d1638cf2f2 100644 --- a/_vendor/github.com/linode/linode-docs-theme/layouts/_default/_markup/render-link.html +++ b/_vendor/github.com/linode/linode-docs-theme/layouts/_default/_markup/render-link.html @@ -1,49 +1,103 @@ {{ $isTest := or (not (not hugo.IsServer)) (site.Params.TestEnv ) }} {{- $link := .Destination -}} {{- $isRemote := strings.Contains $link "://" -}} +{{- $isCard := false -}} {{- $fragment := "" -}} +{{- $page := "" -}} {{- if not $isRemote -}} -{{- $url := urls.Parse .Destination -}} -{{- $fragment = $url.Fragment -}} -{{ $path := "" }} -{{- if and (not $isRemote) $isTest $url.Path -}} - {{/* Check that the target exists. */}} + {{- $url := urls.Parse .Destination -}} + {{- $fragment = $url.Fragment -}} + {{- if $url.Query.Has "cardstyling" }} + {{- $isCard = true -}} + {{- $params := slice -}} + {{- range $k, $v := $url.Query -}} + {{- if ne $k "cardstyling" -}} + {{- $params = $params | append (slice $k ($url.Query.Get $k)) -}} + {{- end -}} + {{- end -}} + {{- $link = $url.Path -}} + {{- with $params -}} + {{- $link = printf "%s?%s" $link (collections.Querify .) -}} + {{ end }} + {{- end -}} {{- $m := partialCached "funcs/get-linkmap.html" "-" -}} - {{ $path = $url.Path}} - {{ $destination := .Destination }} - {{ $hasDot := strings.Contains $path "." }} - {{ if and (not $hasDot) (not (strings.HasSuffix $path "/")) }} - {{ $path = printf "%s/" $path }} - {{ end }} - {{ $ok := true }} - {{ $reason := "" }} - {{- $page := index $m.links $path -}} - {{- if $page -}} - {{/* Page found OK, check for fragment match. */}} - {{- with $url.Fragment }} - {{/* The API section isn't built from Markdown. */}} - {{ if not (eq $page.Section "api") }} - {{ if not ($page.Fragments.Identifiers.Contains .) }} - {{ $ok = false }} - {{ $reason = "Fragment not found" }} + {{- $path := $url.Path -}} + {{- $hasDot := strings.Contains $path "." -}} + {{- if and (not $hasDot) (not (strings.HasSuffix $path "/")) -}} + {{- $path = printf "%s/" $path -}} + {{- end -}} + {{- $page = index $m.links $path -}} + {{- if and (not $isRemote) $isTest $url.Path -}} + {{- $m := partialCached "funcs/get-linkmap.html" "-" -}} + {{ $path = $url.Path }} + {{ $hasDot := strings.Contains $path "." }} + {{ if and (not $hasDot) (not (strings.HasSuffix $path "/")) }} + {{ $path = printf "%s/" $path }} + {{ end }} + {{- $page := index $m.links $path -}} + {{ $ok := true }} + {{ $reason := "" }} + {{- if $page -}} + {{/* Page found OK, check for fragment match. */}} + {{- with $url.Fragment }} + {{/* The API section isn't built from Markdown. */}} + {{ if not (eq $page.Section "api") }} + {{ if not ($page.Fragments.Identifiers.Contains .) }} + {{ $ok = false }} + {{ $reason = "Fragment not found" }} + {{ end }} {{ end }} + {{ end -}} + {{ else }} + {{ $ok = false }} + {{ $reason = "Not found" }} + {{ end }} + {{ if not $ok }} + {{/* Store it away so we can build a report later. */}} + {{ if not (strings.HasPrefix $path "/") }} + {{ $path = path.Join $.Page.RelPermalink $path }} {{ end }} - {{ end -}} - {{ else }} - {{ $ok = false }} - {{ $reason = "Not found" }} - {{ end }} - {{ if not $ok }} - {{/* Store it away so we can build a report later. */}} - {{ if not (strings.HasPrefix $path "/") }} - {{ $path = path.Join $.Page.RelPermalink $path }} + {{ $path = strings.TrimPrefix "/docs" $path }} + {{ $m := dict "link" .Destination "path" $path "fragment" $fragment "reason" $reason "sourceRef" $.Page.RelPermalink "source" $.Page "target" $page }} + {{ site.Home.Store.SetInMap "brokenlinks" .Destination $m }} + {{ else }} + {{ site.Home.Store.DeleteInMap "brokenlinks" .Destination }} {{ end }} - {{ $path = strings.TrimPrefix "/docs" $path }} - {{ $m := dict "link" .Destination "path" $path "fragment" $fragment "reason" $reason "sourceRef" $.Page.RelPermalink "source" $.Page "target" $page }} - {{ site.Home.Store.SetInMap "brokenlinks" .Destination $m }} - {{ else }} - {{ site.Home.Store.DeleteInMap "brokenlinks" .Destination }} - {{ end }} + {{- end -}} {{- end -}} +{{- if $isCard -}} + {{ template "render-card-link" (dict "dot" . "link" $link "page" $page ) }} +{{- else -}} + {{ .Text | safeHTML }} {{- end -}} -{{ .Text | safeHTML }} \ No newline at end of file +{{ define "render-card-link" }} + {{- $title := .dot.Title -}} + {{- $text := .dot.Text }} + {{- if .page -}} + {{- $title = .page.LinkTitle -}} + {{- end -}} + {{- if and .page .page.Params.description -}} + {{- $text = .page.Params.description | markdownify -}} + {{- end -}} + + +

+{{ end }} diff --git a/_vendor/github.com/linode/linode-docs-theme/layouts/_default/list.html b/_vendor/github.com/linode/linode-docs-theme/layouts/_default/list.html index b6bd615de96..5a689e784c0 100644 --- a/_vendor/github.com/linode/linode-docs-theme/layouts/_default/list.html +++ b/_vendor/github.com/linode/linode-docs-theme/layouts/_default/list.html @@ -221,10 +221,9 @@